func dataSourceAlibabacloudStackZonesRead()

in alibabacloudstack/data_source_apsarastack_zones.go [185:584]


func dataSourceAlibabacloudStackZonesRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*connectivity.AlibabacloudStackClient)
	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)
	elasticsearchZones := make(map[string]string)
	instanceChargeType := d.Get("instance_charge_type").(string)

	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeRds)) {
		request := rds.CreateDescribeRegionsRequest()
		client.InitRpcRequest(*request.RpcRequest)
		var raw interface{}
		var err error
		err = resource.Retry(5*time.Minute, func() *resource.RetryError {
			raw, err = client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) {
				return rdsClient.DescribeRegions(request)
			})
			if err != nil {
				if errmsgs.IsExpectedErrors(err, []string{errmsgs.Throttling}) {
					time.Sleep(time.Duration(5) * time.Second)
					return resource.RetryableError(err)
				}
				return resource.NonRetryableError(err)
			}
			addDebug(request.GetActionName(), raw, request.RpcRequest, request)

			return nil
		})
		response, ok := raw.(*rds.DescribeRegionsResponse)
		if err != nil {
			errmsg := ""
			if ok {
				errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse)
			}
			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_zones", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
		}
		if len(response.Regions.RDSRegion) <= 0 {
			return errmsgs.WrapError(fmt.Errorf("[ERROR] There is no available zone for RDS."))
		}
		for _, r := range response.Regions.RDSRegion {
			if multi && strings.Contains(r.ZoneId, MULTI_IZ_SYMBOL) && r.RegionId == string(client.Region) {
				zoneIds = append(zoneIds, r.ZoneId)
				continue
			}
			rdsZones[r.ZoneId] = r.RegionId
		}
	}
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeRkv)) {
		request := r_kvstore.CreateDescribeRegionsRequest()
		client.InitRpcRequest(*request.RpcRequest)
		raw, err := client.WithRkvClient(func(rkvClient *r_kvstore.Client) (interface{}, error) {
			return rkvClient.DescribeRegions(request)
		})
		regions, ok := raw.(*r_kvstore.DescribeRegionsResponse)
		if err != nil {
			errmsg := ""
			if ok {
				errmsg = errmsgs.GetBaseResponseErrorMessage(regions.BaseResponse)
			}
			return errmsgs.WrapError(fmt.Errorf("[ERROR] DescribeAvailableResource got an error: %#v  %s", err, errmsg))
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		if len(regions.RegionIds.KVStoreRegion) <= 0 {
			return errmsgs.WrapError(fmt.Errorf("[ERROR] There is no available region for KVStore"))
		}
		for _, r := range regions.RegionIds.KVStoreRegion {
			if len(r.ZoneIdList.ZoneId) > 0 {
				for _, zone_id := range r.ZoneIdList.ZoneId {
					if multi && strings.Contains(zone_id, MULTI_IZ_SYMBOL) && r.RegionId == string(client.Region) {
						zoneIds = append(zoneIds, zone_id)
						continue
					}
					rkvZones[zone_id] = r.RegionId
				}
			} else if r.ZoneIds != "" {
				for _, zoneId := range strings.Split(r.ZoneIds, ",") {
					if multi && strings.Contains(r.ZoneIds, MULTI_IZ_SYMBOL) && r.RegionId == string(client.Region) {
						zoneIds = append(zoneIds, r.ZoneIds)
					}
					rkvZones[zoneId] = r.RegionId
				}
			}
		}
	}
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeMongoDB)) {
		request := dds.CreateDescribeRegionsRequest()
		client.InitRpcRequest(*request.RpcRequest)
		raw, err := client.WithDdsClient(func(ddsClient *dds.Client) (interface{}, error) {
			return ddsClient.DescribeRegions(request)
		})
		regions, ok := raw.(*dds.DescribeRegionsResponse)
		if err != nil {
			errmsg := ""
			if ok {
				errmsg = errmsgs.GetBaseResponseErrorMessage(regions.BaseResponse)
			}
			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_zones", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		if len(regions.Regions.DdsRegion) <= 0 {
			return errmsgs.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()
		client.InitRpcRequest(*request.RpcRequest)
		raw, err := client.WithHbaseClient(func(hbaseClient *hbase.Client) (interface{}, error) {
			return hbaseClient.DescribeRegions(request)
		})
		regions, ok := raw.(*hbase.DescribeRegionsResponse)
		if err != nil {
			errmsg := ""
			if ok {
				errmsg = errmsgs.GetBaseResponseErrorMessage(regions.BaseResponse)
			}
			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_zones", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		if len(regions.Regions.Region) <= 0 {
			return errmsgs.WrapError(fmt.Errorf("[ERROR] There is no available region for HBase."))
		}
		for _, r := range regions.Regions.Region {
			for _, zonid := range r.Zones.Zone {
				if multi && strings.Contains(zonid.Id, MULTI_IZ_SYMBOL) && r.RegionId == string(client.Region) {
					zoneIds = append(zoneIds, zonid.Id)
					continue
				}
				hbaseZones[zonid.Id] = r.RegionId
			}
		}
	}
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeAdb)) {
		request := adb.CreateDescribeRegionsRequest()
		client.InitRpcRequest(*request.RpcRequest)
		raw, err := client.WithAdbClient(func(adbClient *adb.Client) (interface{}, error) {
			return adbClient.DescribeRegions(request)
		})
		regions, ok := raw.(*adb.DescribeRegionsResponse)
		if err != nil {
			errmsg := ""
			if ok {
				errmsg = errmsgs.GetBaseResponseErrorMessage(regions.BaseResponse)
			}
			return errmsgs.WrapError(fmt.Errorf("[ERROR] DescribeRegions got an error: %#v. %s", err, errmsg))
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		if len(regions.Regions.Region) <= 0 {
			return errmsgs.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()
		client.InitRpcRequest(*request.RpcRequest)
		raw, err := client.WithGpdbClient(func(gpdbClient *gpdb.Client) (interface{}, error) {
			return gpdbClient.DescribeRegions(request)
		})
		response, ok := raw.(*gpdb.DescribeRegionsResponse)
		if err != nil {
			errmsg := ""
			if ok {
				errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse)
			}
			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_zones", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		if len(response.Regions.Region) <= 0 {
			return errmsgs.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
			}
		}
	}

	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeElasticsearch)) {
		request := elasticsearch.CreateGetRegionConfigurationRequest()
		client.InitRoaRequest(*request.RoaRequest)
		raw, err := client.WithElasticsearchClient(func(elasticsearchClient *elasticsearch.Client) (interface{}, error) {
			return elasticsearchClient.GetRegionConfiguration(request)
		})
		zones, ok := raw.(*elasticsearch.GetRegionConfigurationResponse)
		if err != nil {
			errmsg := ""
			if ok {
				errmsg = errmsgs.GetBaseResponseErrorMessage(zones.BaseResponse)
			}
			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_zones", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
		}
		addDebug(request.GetActionName(), raw, request.GetActionName(), request)
		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 SLB
	slaveZones := make(map[string][]string)
	if strings.ToLower(Trim(resType)) == strings.ToLower(string(ResourceTypeSlb)) {
		request := slb.CreateDescribeZonesRequest()
		client.InitRpcRequest(*request.RpcRequest)
		raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) {
			return slbClient.DescribeZones(request)
		})
		response, ok := raw.(*slb.DescribeZonesResponse)
		if err != nil {
			errmsg := ""
			if ok {
				errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse)
			}
			return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_zones", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
		}
		addDebug(request.GetActionName(), raw, request.RpcRequest, request)
		for _, resource := range response.Zones.Zone {
			slaveIds := slaveZones[resource.ZoneId]
			if len(slaveIds) > 0 {
				sort.Strings(slaveIds)
			}
			slaveZones[resource.ZoneId] = slaveIds
		}

	}

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

	req := ecs.CreateDescribeZonesRequest()
	client.InitRpcRequest(*req.RpcRequest)
	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)
	})
	resp, ok := raw.(*ecs.DescribeZonesResponse)
	if err != nil {
		errmsg := ""
		if ok {
			errmsg = errmsgs.GetBaseResponseErrorMessage(resp.BaseResponse)
		}
		return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_zones", req.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)
	}
	addDebug(req.GetActionName(), raw, req.RpcRequest, req)
	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) != "" {
		if err := writeToFile(output.(string), s); err != nil {
			return err
		}
	}

	return nil
}