func dataSourceAlicloudZonesRead()

in alicloud/data_source_alicloud_zones.go [181:542]


func dataSourceAlicloudZonesRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*connectivity.AliyunClient)
	ecsService := EcsService{client}

	resType := d.Get("available_resource_creation").(string)
	multi := d.Get("multi").(bool)
	var zoneIds []string
	rdsZones := make(map[string]string)
	polarDBZones := make(map[string]string)
	rkvZones := make(map[string]string)
	mongoDBZones := make(map[string]string)
	gpdbZones := make(map[string]string)
	hbaseZones := make(map[string]string)
	adbZones := make(map[string]string)
	instanceChargeType := d.Get("instance_charge_type").(string)

	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypePolarDB)) {
		request := polardb.CreateDescribeRegionsRequest()
		request.RegionId = client.RegionId
		raw, err := client.WithPolarDBClient(func(polarDBClient *polardb.Client) (interface{}, error) {
			return polarDBClient.DescribeRegions(request)
		})
		if err != nil {
			return WrapError(fmt.Errorf("[ERROR] DescribeRegions got an error: %#v", err))
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		regions, _ := raw.(*polardb.DescribeRegionsResponse)
		if len(regions.Regions.Region) <= 0 {
			return WrapError(fmt.Errorf("[ERROR] There is no available region for PolarDB."))
		}
		for _, r := range regions.Regions.Region {
			for _, zone := range r.Zones.Zone {
				if multi && strings.Contains(zone.ZoneId, MULTI_IZ_SYMBOL) && r.RegionId == string(client.Region) {
					zoneIds = append(zoneIds, zone.ZoneId)
					continue
				}
				polarDBZones[zone.ZoneId] = r.RegionId
			}
		}
	}
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeRkv)) {
		request := r_kvstore.CreateDescribeAvailableResourceRequest()
		request.RegionId = client.RegionId
		request.InstanceChargeType = instanceChargeType
		raw, err := client.WithRKvstoreClient(func(rkvClient *r_kvstore.Client) (interface{}, error) {
			return rkvClient.DescribeAvailableResource(request)
		})
		if err != nil {
			return WrapError(fmt.Errorf("[ERROR] DescribeAvailableResource got an error: %#v", err))
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		zones, _ := raw.(*r_kvstore.DescribeAvailableResourceResponse)
		if len(zones.AvailableZones.AvailableZone) <= 0 {
			return WrapError(fmt.Errorf("[ERROR] There is no available zones for KVStore"))
		}
		for _, zone := range zones.AvailableZones.AvailableZone {
			if multi && strings.Contains(zone.ZoneId, MULTI_IZ_SYMBOL) {
				zoneIds = append(zoneIds, zone.ZoneId)
				continue
			}
			rkvZones[zone.ZoneId] = zone.RegionId
		}
	}
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeMongoDB)) {
		request := dds.CreateDescribeRegionsRequest()
		request.RegionId = client.RegionId
		raw, err := client.WithDdsClient(func(ddsClient *dds.Client) (interface{}, error) {
			return ddsClient.DescribeRegions(request)
		})
		if err != nil {
			return WrapErrorf(err, DataDefaultErrorMsg, "alicloud_zones", request.GetActionName(), AlibabaCloudSdkGoERROR)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		regions, _ := raw.(*dds.DescribeRegionsResponse)
		if len(regions.Regions.DdsRegion) <= 0 {
			return WrapError(fmt.Errorf("[ERROR] There is no available region for MongoDB."))
		}
		for _, r := range regions.Regions.DdsRegion {
			for _, zonid := range r.Zones.Zone {
				if multi && strings.Contains(zonid.ZoneId, MULTI_IZ_SYMBOL) && r.RegionId == string(client.Region) {
					zoneIds = append(zoneIds, zonid.ZoneId)
					continue
				}
				mongoDBZones[zonid.ZoneId] = r.RegionId
			}
		}
	}
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeHBase)) {
		request := hbase.CreateDescribeRegionsRequest()
		request.RegionId = client.RegionId
		raw, err := client.WithHbaseClient(func(hbaseClient *hbase.Client) (interface{}, error) {
			return hbaseClient.DescribeRegions(request)
		})
		if err != nil {
			return WrapErrorf(err, DataDefaultErrorMsg, "alicloud_zones", request.GetActionName(), AlibabaCloudSdkGoERROR)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		regions, _ := raw.(*hbase.DescribeRegionsResponse)
		if len(regions.Regions.Region) <= 0 {
			return WrapError(fmt.Errorf("[ERROR] There is no available region for HBase."))
		}
		for _, r := range regions.Regions.Region {
			for _, zonid := range r.Zones.Zone {
				if r.RegionId == string(client.Region) {
					hbaseZones[zonid.Id] = r.RegionId
				}
			}
		}
	}
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeAdb)) {
		request := adb.CreateDescribeRegionsRequest()
		request.RegionId = client.RegionId
		raw, err := client.WithAdbClient(func(adbClient *adb.Client) (interface{}, error) {
			return adbClient.DescribeRegions(request)
		})
		if err != nil {
			return WrapError(fmt.Errorf("[ERROR] DescribeRegions got an error: %#v", err))
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		regions, _ := raw.(*adb.DescribeRegionsResponse)
		if len(regions.Regions.Region) <= 0 {
			return WrapError(fmt.Errorf("[ERROR] There is no available region for adb."))
		}
		for _, r := range regions.Regions.Region {
			for _, zone := range r.Zones.Zone {
				if multi && strings.Contains(zone.ZoneId, MULTI_IZ_SYMBOL) && r.RegionId == string(client.Region) {
					zoneIds = append(zoneIds, zone.ZoneId)
					continue
				}
				adbZones[zone.ZoneId] = r.RegionId
			}
		}
	}
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeGpdb)) {
		request := gpdb.CreateDescribeRegionsRequest()
		request.RegionId = client.RegionId
		raw, err := client.WithGpdbClient(func(gpdbClient *gpdb.Client) (interface{}, error) {
			return gpdbClient.DescribeRegions(request)
		})
		if err != nil {
			return WrapErrorf(err, DataDefaultErrorMsg, "alicloud_zones", request.GetActionName(), AlibabaCloudSdkGoERROR)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		response, _ := raw.(*gpdb.DescribeRegionsResponse)
		if len(response.Regions.Region) <= 0 {
			return WrapError(fmt.Errorf("[ERROR] There is no available region for gpdb."))
		}
		for _, r := range response.Regions.Region {
			for _, zoneId := range r.Zones.Zone {
				if multi && strings.Contains(zoneId.ZoneId, MULTI_IZ_SYMBOL) && r.RegionId == string(client.Region) {
					zoneIds = append(zoneIds, zoneId.ZoneId)
					continue
				}
				gpdbZones[zoneId.ZoneId] = r.RegionId
			}
		}
	}
	elasticsearchZones := make(map[string]string)
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeElasticsearch)) {
		request := elasticsearch.CreateGetRegionConfigurationRequest()
		request.RegionId = client.RegionId
		raw, err := client.WithElasticsearchClient(func(elasticsearchClient *elasticsearch.Client) (interface{}, error) {
			return elasticsearchClient.GetRegionConfiguration(request)
		})

		if err != nil {
			return WrapErrorf(err, DataDefaultErrorMsg, "alicloud_zones", request.GetActionName(), AlibabaCloudSdkGoERROR)
		}
		addDebug(request.GetActionName(), raw, request.GetActionName(), request)
		zones, _ := raw.(*elasticsearch.GetRegionConfigurationResponse)
		for _, zoneID := range zones.Result.Zones {
			if multi && strings.Contains(zoneID, MULTI_IZ_SYMBOL) {
				zoneIds = append(zoneIds, zoneID)
				continue
			}

			elasticsearchZones[zoneID] = string(client.Region)
		}
	}

	if len(zoneIds) > 0 {
		sort.Strings(zoneIds)
		return zoneIdsDescriptionAttributes(d, zoneIds)
	}

	// Retrieving available zones for VPC-FC
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeFC)) {
		var clientInfo *fc.Client
		raw, err := client.WithFcClient(func(fcClient *fc.Client) (interface{}, error) {
			clientInfo = fcClient
			return fcClient.GetAccountSettings(fc.NewGetAccountSettingsInput())
		})
		if err != nil {
			return fmt.Errorf("[API ERROR] FC GetAccountSettings: %#v", err)
		}
		addDebug("GetAccountSettings", raw, clientInfo)
		out, _ := raw.(*fc.GetAccountSettingsOutput)
		if out != nil && len(out.AvailableAZs) > 0 {
			sort.Strings(out.AvailableAZs)
			return zoneIdsDescriptionAttributes(d, out.AvailableAZs)
		}
	}

	// Retrieving available zones for SLB
	slaveZones := make(map[string][]string)
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeSlb)) {
		request := slb.CreateDescribeAvailableResourceRequest()
		request.RegionId = client.RegionId
		if ipVersion, ok := d.GetOk("available_slb_address_ip_version"); ok {
			request.AddressIPVersion = ipVersion.(string)
		}
		if addressType, ok := d.GetOk("available_slb_address_type"); ok {
			request.AddressType = addressType.(string)
		}
		raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) {
			return slbClient.DescribeAvailableResource(request)
		})
		if err != nil {
			return WrapErrorf(err, DataDefaultErrorMsg, "alicloud_zones", request.GetActionName(), AlibabaCloudSdkGoERROR)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		response, _ := raw.(*slb.DescribeAvailableResourceResponse)
		for _, resource := range response.AvailableResources.AvailableResource {
			slaveIds := slaveZones[resource.MasterZoneId]
			slaveIds = append(slaveIds, resource.SlaveZoneId)
			if len(slaveIds) > 0 {
				sort.Strings(slaveIds)
			}
			slaveZones[resource.MasterZoneId] = slaveIds
		}
	}

	_, validZones, _, err := ecsService.DescribeAvailableResources(d, meta, ZoneResource)
	if err != nil {
		return err
	}

	req := ecs.CreateDescribeZonesRequest()
	req.RegionId = client.RegionId
	req.InstanceChargeType = instanceChargeType
	if v, ok := d.GetOk("spot_strategy"); ok && v.(string) != "" {
		req.SpotStrategy = v.(string)
	}

	raw, err := client.WithEcsClient(func(ecsClient *ecs.Client) (interface{}, error) {
		return ecsClient.DescribeZones(req)
	})
	if err != nil {
		return fmt.Errorf("DescribeZones got an error: %#v", err)
	}
	addDebug(req.GetActionName(), raw, req.RpcRequest, req)
	resp, _ := raw.(*ecs.DescribeZonesResponse)
	if resp == nil || len(resp.Zones.Zone) < 1 {
		return fmt.Errorf("There are no availability zones in the region: %#v.", client.Region)
	}

	mapZones := make(map[string]ecs.Zone)
	insType, _ := d.Get("available_instance_type").(string)
	diskType, _ := d.Get("available_disk_category").(string)

	for _, zone := range resp.Zones.Zone {
		for _, v := range validZones {
			if zone.ZoneId != v.ZoneId {
				continue
			}
			if len(zone.AvailableInstanceTypes.InstanceTypes) <= 0 ||
				(insType != "" && !constraints(zone.AvailableInstanceTypes.InstanceTypes, insType)) {
				continue
			}
			if len(zone.AvailableDiskCategories.DiskCategories) <= 0 ||
				(diskType != "" && !constraints(zone.AvailableDiskCategories.DiskCategories, diskType)) {
				continue
			}
			if len(rdsZones) > 0 {
				if _, ok := rdsZones[zone.ZoneId]; !ok {
					continue
				}
			}
			if len(polarDBZones) > 0 {
				if _, ok := polarDBZones[zone.ZoneId]; !ok {
					continue
				}
			}
			if len(rkvZones) > 0 {
				if _, ok := rkvZones[zone.ZoneId]; !ok {
					continue
				}
			}
			if len(mongoDBZones) > 0 {
				if _, ok := mongoDBZones[zone.ZoneId]; !ok {
					continue
				}
			}
			if len(hbaseZones) > 0 {
				if _, ok := hbaseZones[zone.ZoneId]; !ok {
					continue
				}
			}
			if len(gpdbZones) > 0 {
				if _, ok := gpdbZones[zone.ZoneId]; !ok {
					continue
				}
			}
			if len(elasticsearchZones) > 0 {
				if _, ok := elasticsearchZones[zone.ZoneId]; !ok {
					continue
				}
			}
			if len(slaveZones) > 0 {
				if _, ok := slaveZones[zone.ZoneId]; !ok {
					continue
				}
			}
			if len(adbZones) > 0 {
				if _, ok := adbZones[zone.ZoneId]; !ok {
					continue
				}
			}

			zoneIds = append(zoneIds, zone.ZoneId)
			mapZones[zone.ZoneId] = zone
		}
	}

	if len(zoneIds) > 0 {
		// Sort zones before reading
		sort.Strings(zoneIds)
	}

	var s []map[string]interface{}
	for _, zoneId := range zoneIds {
		mapping := map[string]interface{}{"id": zoneId}
		if len(slaveZones) > 0 {
			mapping["slb_slave_zone_ids"] = slaveZones[zoneId]
		}
		if !d.Get("enable_details").(bool) {
			s = append(s, mapping)
			continue
		}
		mapping["local_name"] = mapZones[zoneId].LocalName
		mapping["available_instance_types"] = mapZones[zoneId].AvailableInstanceTypes.InstanceTypes
		mapping["available_resource_creation"] = mapZones[zoneId].AvailableResourceCreation.ResourceTypes
		mapping["available_disk_categories"] = mapZones[zoneId].AvailableDiskCategories.DiskCategories
		s = append(s, mapping)
	}

	d.SetId(dataResourceIdHash(zoneIds))
	if err := d.Set("zones", s); err != nil {
		return err
	}

	if err := d.Set("ids", zoneIds); err != nil {
		return err
	}

	// create a json file in current directory and write data source to it.
	if output, ok := d.GetOk("output_file"); ok && output.(string) != "" {
		writeToFile(output.(string), s)
	}

	return nil
}