diff --git a/cmd/openshift-install/destroy.go b/cmd/openshift-install/destroy.go index aa6978e4dea..34d2f480e6b 100644 --- a/cmd/openshift-install/destroy.go +++ b/cmd/openshift-install/destroy.go @@ -10,6 +10,7 @@ import ( assetstore "github.com/openshift/installer/pkg/asset/store" "github.com/openshift/installer/pkg/destroy" + _ "github.com/openshift/installer/pkg/destroy/alibabacloud" _ "github.com/openshift/installer/pkg/destroy/aws" _ "github.com/openshift/installer/pkg/destroy/azure" _ "github.com/openshift/installer/pkg/destroy/baremetal" diff --git a/pkg/destroy/alibabacloud/alibabacloud.go b/pkg/destroy/alibabacloud/alibabacloud.go new file mode 100644 index 00000000000..fb1656082de --- /dev/null +++ b/pkg/destroy/alibabacloud/alibabacloud.go @@ -0,0 +1,1346 @@ +package alibabacloud + +import ( + "encoding/json" + "fmt" + "strings" + "sync" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/services/alidns" + "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" + "github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz" + "github.com/aliyun/alibaba-cloud-sdk-go/services/ram" + "github.com/aliyun/alibaba-cloud-sdk-go/services/resourcemanager" + "github.com/aliyun/alibaba-cloud-sdk-go/services/slb" + "github.com/aliyun/alibaba-cloud-sdk-go/services/tag" + "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "k8s.io/apimachinery/pkg/util/wait" + + icalibabacloud "github.com/openshift/installer/pkg/asset/installconfig/alibabacloud" + "github.com/openshift/installer/pkg/destroy/providers" + "github.com/openshift/installer/pkg/types" +) + +// ClusterUninstaller holds the various options for the cluster we want to delete +type ClusterUninstaller struct { + Logger logrus.FieldLogger + AccessKeyID string + AccessKeySecret string + Auth auth.Credential + + Region string + InfraID string + ClusterDomain string + Tags []map[string]string + TagResources struct { + ecsInstances []ResourceArn + securityGroups []ResourceArn + vpcs []ResourceArn + vSwitchs []ResourceArn + eips []ResourceArn + natgateways []ResourceArn + slbs []ResourceArn + others []ResourceArn + } + + ecsClient *ecs.Client + dnsClient *alidns.Client + pvtzClient *pvtz.Client + vpcClient *vpc.Client + ramClient *ram.Client + tagClient *tag.Client + slbClient *slb.Client + ossClient *oss.Client + rmanagerClient *resourcemanager.Client +} + +// ResourceArn holds the information contained in the cloud resource Arn string +type ResourceArn struct { + Service string + Region string + Account string + ResourceType string + ResourceID string + Arn string +} + +func (o *ClusterUninstaller) configureClients() error { + var err error + config := sdk.NewConfig() + config.AutoRetry = true + config.MaxRetryTime = 3 + ossEndpoint := fmt.Sprintf("http://oss-%s.aliyuncs.com", o.Region) + + o.ecsClient, err = ecs.NewClientWithOptions(o.Region, config, o.Auth) + if err != nil { + return err + } + + o.dnsClient, err = alidns.NewClientWithOptions(o.Region, config, o.Auth) + if err != nil { + return err + } + + o.pvtzClient, err = pvtz.NewClientWithOptions(o.Region, config, o.Auth) + if err != nil { + return err + } + + o.ramClient, err = ram.NewClientWithOptions(o.Region, config, o.Auth) + if err != nil { + return err + } + + o.vpcClient, err = vpc.NewClientWithOptions(o.Region, config, o.Auth) + if err != nil { + return err + } + + o.tagClient, err = tag.NewClientWithOptions(o.Region, config, o.Auth) + if err != nil { + return err + } + + o.slbClient, err = slb.NewClientWithOptions(o.Region, config, o.Auth) + if err != nil { + return err + } + + o.ossClient, err = oss.New(ossEndpoint, o.AccessKeyID, o.AccessKeySecret) + if err != nil { + return err + } + + o.rmanagerClient, err = resourcemanager.NewClientWithOptions(o.Region, config, o.Auth) + if err != nil { + return err + } + + return nil +} + +// New returns an Alibaba Cloud destroyer from ClusterMetadata. +func New(logger logrus.FieldLogger, metadata *types.ClusterMetadata) (providers.Destroyer, error) { + region := metadata.ClusterPlatformMetadata.AlibabaCloud.Region + client, err := icalibabacloud.NewClient(region) + if err != nil { + return nil, err + } + + auth := credentials.NewAccessKeyCredential(client.AccessKeyID, client.AccessKeySecret) + + return &ClusterUninstaller{ + Logger: logger, + Auth: auth, + AccessKeyID: client.AccessKeyID, + AccessKeySecret: client.AccessKeySecret, + Region: region, + InfraID: metadata.InfraID, + ClusterDomain: metadata.AlibabaCloud.ClusterDomain, + Tags: []map[string]string{ + { + fmt.Sprintf("kubernetes.io/cluster/%s", metadata.InfraID): "owned", + }, + { + "ack.aliyun.com": metadata.InfraID, + }, + }, + }, nil +} + +// Run is the entrypoint to start the uninstall process. +func (o *ClusterUninstaller) Run() (*types.ClusterQuota, error) { + var err error + + err = o.configureClients() + if err != nil { + return nil, err + } + + err = o.findResources() + if err != nil { + return nil, err + } + + err = o.destroyCluster() + if err != nil { + return nil, errors.Wrap(err, "failed to destroy cluster") + } + + return nil, nil +} + +func (o *ClusterUninstaller) destroyCluster() error { + stagedFuncs := [][]struct { + name string + execute func() error + }{ + { + {name: "DNS records", execute: o.deleteDNSRecords}, + {name: "OSS buckets", execute: o.deleteBucket}, + {name: "RAM roles", execute: o.deleteRAMRoles}, + {name: "ECS instances", execute: o.deleteEcsInstances}, + }, + { + {name: "private zones", execute: o.deletePrivateZones}, + {name: "ECS security groups", execute: o.deleteSecurityGroups}, + {name: "Nat gateways", execute: o.deleteNatGateways}, + {name: "SLBs", execute: o.deleteSlbs}, + }, + { + {name: "EIPs", execute: o.deleteEips}, + }, + { + {name: "VSwitchs", execute: o.deleteVSwitchs}, + }, + { + {name: "VPCs", execute: o.deleteVpcs}, + }, + { + {name: "resource groups", execute: o.deleteResourceGroup}, + }, + } + + for _, stage := range stagedFuncs { + var wg sync.WaitGroup + errCh := make(chan error) + wgDone := make(chan bool) + + for _, f := range stage { + wg.Add(1) + go o.executeStageFunction(f, errCh, &wg) + } + + go func() { + wg.Wait() + close(wgDone) + }() + + select { + case <-wgDone: + // On to the next stage + continue + case err := <-errCh: + return err + } + } + + return nil +} + +func (o *ClusterUninstaller) executeStageFunction(f struct { + name string + execute func() error +}, errCh chan error, wg *sync.WaitGroup) error { + defer wg.Done() + + err := wait.PollImmediateInfinite( + time.Second*10, + func() (bool, error) { + ferr := f.execute() + if ferr != nil { + o.Logger.Debugf("%s: %v", f.name, ferr) + return false, nil + } + return true, nil + }, + ) + + if err != nil { + errCh <- err + } + return nil +} + +func (o *ClusterUninstaller) findResources() (err error) { + tagResources, err := o.findResourcesByTag() + if err != nil { + return errors.Wrap(err, "failed to find resource by tag") + } + if len(tagResources) > 0 { + var deletedResources []ResourceArn + for _, resource := range tagResources { + arn, err := convertResourceArn(resource.ResourceARN) + if err != nil { + continue + } + deletedResources = append(deletedResources, arn) + } + + o.tidyResourceByArn(deletedResources) + } + return nil +} + +func (o *ClusterUninstaller) tidyResourceByArn(resourceArns []ResourceArn) { + for _, resourceArn := range resourceArns { + switch resourceArn.Service { + case "ecs": + switch resourceArn.ResourceType { + case "instance": + o.TagResources.ecsInstances = append(o.TagResources.ecsInstances, resourceArn) + case "securitygroup": + o.TagResources.securityGroups = append(o.TagResources.securityGroups, resourceArn) + default: + o.TagResources.others = append(o.TagResources.others, resourceArn) + } + case "vpc": + switch resourceArn.ResourceType { + case "vpc": + o.TagResources.vpcs = append(o.TagResources.vpcs, resourceArn) + case "vswitch": + o.TagResources.vSwitchs = append(o.TagResources.vSwitchs, resourceArn) + case "eip": + o.TagResources.eips = append(o.TagResources.eips, resourceArn) + case "natgateway": + o.TagResources.natgateways = append(o.TagResources.natgateways, resourceArn) + default: + o.TagResources.others = append(o.TagResources.others, resourceArn) + } + case "slb": + switch resourceArn.ResourceType { + case "instance": + o.TagResources.slbs = append(o.TagResources.slbs, resourceArn) + default: + o.TagResources.others = append(o.TagResources.others, resourceArn) + } + default: + o.TagResources.others = append(o.TagResources.others, resourceArn) + } + } +} + +func (o *ClusterUninstaller) deleteResourceGroup() (err error) { + resourceGroupName := fmt.Sprintf("%s-rg", o.InfraID) + response, err := o.listResourceGroups() + if err != nil { + return err + } + + resourceGroupID := "" + for _, resourceGroup := range response.ResourceGroups.ResourceGroup { + if resourceGroup.Name == resourceGroupName { + resourceGroupID = resourceGroup.Id + } + } + + if resourceGroupID == "" { + return + } + + o.Logger.Debugf("Start to delete resource group %q", resourceGroupID) + err = o.deleteResourceGroupByID(resourceGroupID) + if err != nil { + return err + } + + err = wait.Poll( + 2*time.Second, + 1*time.Minute, + func() (bool, error) { + response, err := o.listResourceGroups() + if err != nil { + return false, err + } + for _, resourceGroup := range response.ResourceGroups.ResourceGroup { + if resourceGroup.Name == resourceGroupName { + return false, nil + } + } + return true, nil + }, + ) + + return +} + +func (o *ClusterUninstaller) deleteResourceGroupByID(resourceGroupID string) (err error) { + request := resourcemanager.CreateDeleteResourceGroupRequest() + request.Scheme = "https" + request.ResourceGroupId = resourceGroupID + _, err = o.rmanagerClient.DeleteResourceGroup(request) + return +} + +func (o *ClusterUninstaller) listResourceGroups() (response *resourcemanager.ListResourceGroupsResponse, err error) { + request := resourcemanager.CreateListResourceGroupsRequest() + request.Scheme = "https" + response, err = o.rmanagerClient.ListResourceGroups(request) + return +} + +func (o *ClusterUninstaller) deleteBucket() (err error) { + bucketName := fmt.Sprintf("%s-bootstrap", o.InfraID) + result, err := o.ossClient.ListBuckets(oss.Prefix(bucketName)) + if err != nil || len(result.Buckets) == 0 { + return + } + + o.Logger.Debugf("Start to delete buckets %q", bucketName) + + keys := []string{fmt.Sprintf("kubernetes.io/cluster/%s", o.InfraID)} + arns := []string{fmt.Sprintf("arn:acs:oss:%s:*:bucket/%s", o.Region, bucketName)} + err = o.unTagResource(&keys, &arns) + if err != nil { + return err + } + + bucket, err := o.ossClient.Bucket(bucketName) + if err != nil { + return err + } + + err = o.deleteObjects(bucket) + if err != nil { + return err + } + + err = o.ossClient.DeleteBucket(bucketName) + if err != nil { + return err + } + + err = wait.Poll( + 2*time.Second, + 2*time.Minute, + func() (bool, error) { + result, err := o.ossClient.ListBuckets(oss.Prefix(bucketName)) + if err != nil { + return false, err + } + if len(result.Buckets) == 0 { + return true, nil + } + return false, nil + }, + ) + + return +} + +func (o *ClusterUninstaller) deleteObjects(bucket *oss.Bucket) (err error) { + result, err := bucket.ListObjectsV2() + if err != nil { + return err + } + if len(result.Objects) == 0 { + return + } + + o.Logger.Debugf("Start to delete objects of buckets %s", bucket.BucketName) + var keys []string + + for _, object := range result.Objects { + keys = append(keys, object.Key) + } + bucket.DeleteObjects(keys) + + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + result, err := bucket.ListObjectsV2() + if err != nil { + return false, err + } + if len(result.Objects) == 0 { + return true, nil + } + return false, nil + }, + ) + return +} + +func (o *ClusterUninstaller) deleteSlbs() (err error) { + if len(o.TagResources.slbs) <= 0 { + return nil + } + + var slbIDs []string + for _, slbArn := range o.TagResources.slbs { + slbIDs = append(slbIDs, slbArn.ResourceID) + } + + o.Logger.Debugf("Start to delete SLBs %q", slbIDs) + for _, slbID := range slbIDs { + err = o.setSlbModificationProtection(slbID) + if err != nil { + return err + } + err = o.setSlbDeleteProtection(slbID) + if err != nil { + return err + } + err = o.deleteSlb(slbID) + if err != nil { + return err + } + } + + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + response, err := o.listSlb(slbIDs) + if err != nil { + return false, err + } + if response.TotalCount == 0 { + return true, nil + } + return false, nil + }, + ) + return +} + +func (o *ClusterUninstaller) listSlb(slbIDs []string) (response *slb.DescribeLoadBalancersResponse, err error) { + request := slb.CreateDescribeLoadBalancersRequest() + request.LoadBalancerId = strings.Join(slbIDs, ",") + response, err = o.slbClient.DescribeLoadBalancers(request) + return +} + +func (o *ClusterUninstaller) setSlbModificationProtection(slbID string) (err error) { + request := slb.CreateSetLoadBalancerModificationProtectionRequest() + request.LoadBalancerId = slbID + request.ModificationProtectionStatus = "NonProtection" + _, err = o.slbClient.SetLoadBalancerModificationProtection(request) + return +} + +func (o *ClusterUninstaller) setSlbDeleteProtection(slbID string) (err error) { + request := slb.CreateSetLoadBalancerDeleteProtectionRequest() + request.LoadBalancerId = slbID + request.DeleteProtection = "off" + _, err = o.slbClient.SetLoadBalancerDeleteProtection(request) + return +} + +func (o *ClusterUninstaller) deleteSlb(slbID string) (err error) { + o.Logger.Debugf("Start to delete SLB %q", slbID) + request := slb.CreateDeleteLoadBalancerRequest() + request.LoadBalancerId = slbID + _, err = o.slbClient.DeleteLoadBalancer(request) + return +} + +func (o *ClusterUninstaller) deleteVSwitchs() (err error) { + if len(o.TagResources.vSwitchs) <= 0 { + return nil + } + + var vSwitchIDs []string + for _, vSwitchArn := range o.TagResources.vSwitchs { + vSwitchIDs = append(vSwitchIDs, vSwitchArn.ResourceID) + } + + o.Logger.Debugf("Start to delete VSwitchs %q", vSwitchIDs) + for _, vSwitchID := range vSwitchIDs { + err = wait.Poll( + 5*time.Second, + 30*time.Second, + func() (bool, error) { + err = o.deleteVSwitch(vSwitchID) + if err == nil { + return true, nil + } + if strings.Contains(err.Error(), "DependencyViolation") { + return false, nil + } + return false, err + }, + ) + if err != nil { + return err + } + } + + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + response, err := o.listVSwitch(vSwitchIDs) + if err != nil { + return false, err + } + if response.TotalCount == 0 { + return true, nil + } + return false, nil + }, + ) + return +} + +func (o *ClusterUninstaller) listVSwitch(vSwitchIDs []string) (response *vpc.DescribeVSwitchesResponse, err error) { + request := vpc.CreateDescribeVSwitchesRequest() + request.VSwitchId = strings.Join(vSwitchIDs, ",") + response, err = o.vpcClient.DescribeVSwitches(request) + return +} + +func (o *ClusterUninstaller) deleteVSwitch(vSwitchID string) (err error) { + o.Logger.Debugf("Start to delete VSwitch %q", vSwitchID) + request := vpc.CreateDeleteVSwitchRequest() + request.VSwitchId = vSwitchID + _, err = o.vpcClient.DeleteVSwitch(request) + return +} + +func (o *ClusterUninstaller) deleteVpcs() (err error) { + if len(o.TagResources.vpcs) <= 0 { + return nil + } + + var vpcIDs []string + for _, vpcArn := range o.TagResources.vpcs { + vpcIDs = append(vpcIDs, vpcArn.ResourceID) + } + + o.Logger.Debugf("Start to delete VPCs %q", vpcIDs) + for _, vpcID := range vpcIDs { + err = wait.Poll( + 5*time.Second, + 30*time.Second, + func() (bool, error) { + err = o.deleteVpc(vpcID) + if err == nil { + return true, nil + } + if strings.Contains(err.Error(), "DependencyViolation") { + return false, nil + } + return false, err + }, + ) + if err != nil { + return err + } + } + + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + response, err := o.listVpc(vpcIDs) + if err != nil { + return false, err + } + if response.TotalCount == 0 { + return true, nil + } + return false, nil + }, + ) + + return +} + +func (o *ClusterUninstaller) deleteVpc(vpcID string) (err error) { + o.Logger.Debugf("Start to delete VPC %q", vpcID) + request := vpc.CreateDeleteVpcRequest() + request.VpcId = vpcID + _, err = o.vpcClient.DeleteVpc(request) + return +} + +func (o *ClusterUninstaller) listVpc(vpcIDs []string) (response *vpc.DescribeVpcsResponse, err error) { + request := vpc.CreateDescribeVpcsRequest() + request.VpcId = strings.Join(vpcIDs, ",") + response, err = o.vpcClient.DescribeVpcs(request) + return +} + +func (o *ClusterUninstaller) deleteEips() (err error) { + if len(o.TagResources.eips) <= 0 { + return nil + } + + var eipIDs []string + for _, eipArn := range o.TagResources.eips { + eipIDs = append(eipIDs, eipArn.ResourceID) + } + + o.Logger.Debugf("Start to delete EIPs %q", eipIDs) + for _, eipID := range eipIDs { + err = o.deleteEip(eipID) + if err != nil { + return err + } + } + err = wait.Poll( + 2*time.Second, + 2*time.Minute, + func() (bool, error) { + response, err := o.listEip(eipIDs) + if err != nil { + return false, err + } + if response.TotalCount == 0 { + return true, nil + } + return false, nil + }, + ) + return err +} + +func (o *ClusterUninstaller) listEip(eipIDs []string) (response *vpc.DescribeEipAddressesResponse, err error) { + request := vpc.CreateDescribeEipAddressesRequest() + request.AllocationId = strings.Join(eipIDs, ",") + response, err = o.vpcClient.DescribeEipAddresses(request) + return response, err +} + +func (o *ClusterUninstaller) deleteEip(eipID string) (err error) { + o.Logger.Debugf("Start to delete EIP %q", eipID) + request := vpc.CreateReleaseEipAddressRequest() + request.AllocationId = eipID + _, err = o.vpcClient.ReleaseEipAddress(request) + return +} + +func (o *ClusterUninstaller) deleteNatGateways() (err error) { + if len(o.TagResources.natgateways) <= 0 { + return nil + } + + var natGatewayIDs []string + for _, natGatewayArn := range o.TagResources.natgateways { + natGatewayIDs = append(natGatewayIDs, natGatewayArn.ResourceID) + } + + o.Logger.Debugf("Start to delete NAT gateways %q", natGatewayIDs) + for _, natGatewayID := range natGatewayIDs { + err = o.deleteNatGateway(natGatewayID) + if err != nil { + return err + } + err = wait.Poll( + 3*time.Second, + 3*time.Minute, + func() (bool, error) { + response, err := o.listNatGateways(natGatewayID) + if err != nil { + return false, err + } + if response.TotalCount == 0 { + return true, nil + } + return false, nil + }, + ) + if err != nil { + return err + } + } + return +} + +func (o *ClusterUninstaller) listNatGateways(natGatewayID string) (response *vpc.DescribeNatGatewaysResponse, err error) { + request := vpc.CreateDescribeNatGatewaysRequest() + request.NatGatewayId = natGatewayID + response, err = o.vpcClient.DescribeNatGateways(request) + return +} + +func (o *ClusterUninstaller) deleteNatGateway(natGatewayID string) (err error) { + o.Logger.Debugf("Start to delete NAT gateway %q", natGatewayID) + request := vpc.CreateDeleteNatGatewayRequest() + request.NatGatewayId = natGatewayID + request.Force = "true" + _, err = o.vpcClient.DeleteNatGateway(request) + return +} + +func (o *ClusterUninstaller) deleteSecurityGroups() (err error) { + if len(o.TagResources.securityGroups) <= 0 { + return nil + } + + var securityGroupIDs []string + for _, securityGroupArn := range o.TagResources.securityGroups { + securityGroupIDs = append(securityGroupIDs, securityGroupArn.ResourceID) + } + + o.Logger.Debugf("Start to delete security groups %q", securityGroupIDs) + + for _, securityGroupID := range securityGroupIDs { + err = o.deleteSecurityGroupRules(securityGroupID) + if err != nil { + return err + } + } + + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + response, err := o.listSecurityGroupReferences(securityGroupIDs) + if err != nil { + return false, err + } + if len(response.SecurityGroupReferences.SecurityGroupReference) == 0 { + return true, nil + } + return false, nil + }, + ) + if err != nil { + return err + } + + for _, securityGroupID := range securityGroupIDs { + err = wait.Poll( + 5*time.Second, + 30*time.Second, + func() (bool, error) { + err = o.deleteSecurityGroup(securityGroupID) + if err == nil { + return true, nil + } + if strings.Contains(err.Error(), "DependencyViolation") { + return false, nil + } + return false, err + }, + ) + if err != nil { + return err + } + } + + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + response, err := o.listSecurityGroup(securityGroupIDs) + if err != nil { + return false, err + } + if response.TotalCount == 0 { + return true, nil + } + return false, nil + }, + ) + + return +} + +func (o *ClusterUninstaller) deleteSecurityGroup(securityGroupID string) (err error) { + o.Logger.Debugf("Start to delete security group %q", securityGroupID) + request := ecs.CreateDeleteSecurityGroupRequest() + request.SecurityGroupId = securityGroupID + _, err = o.ecsClient.DeleteSecurityGroup(request) + return +} + +func (o *ClusterUninstaller) deleteSecurityGroupRules(securityGroupID string) (err error) { + o.Logger.Debugf("Start to delete security group %q rules ", securityGroupID) + response, err := o.getSecurityGroup(securityGroupID) + if err != nil { + return err + } + for _, permission := range response.Permissions.Permission { + if permission.SourceGroupId != "" { + err = o.revokeSecurityGroup(securityGroupID, permission.SourceGroupId, permission.IpProtocol, permission.PortRange, permission.NicType) + } + } + return +} + +func (o *ClusterUninstaller) revokeSecurityGroup(securityGroupID string, sourceGroupID string, ipProtocol string, portRange string, nicType string) (err error) { + request := ecs.CreateRevokeSecurityGroupRequest() + request.SecurityGroupId = securityGroupID + request.SourceGroupId = sourceGroupID + request.IpProtocol = ipProtocol + request.PortRange = portRange + request.NicType = nicType + + _, err = o.ecsClient.RevokeSecurityGroup(request) + return +} + +func (o *ClusterUninstaller) getSecurityGroup(securityGroupID string) (response *ecs.DescribeSecurityGroupAttributeResponse, err error) { + request := ecs.CreateDescribeSecurityGroupAttributeRequest() + request.SecurityGroupId = securityGroupID + response, err = o.ecsClient.DescribeSecurityGroupAttribute(request) + return +} + +func (o *ClusterUninstaller) listSecurityGroupReferences(securityGroupIDs []string) (response *ecs.DescribeSecurityGroupReferencesResponse, err error) { + request := ecs.CreateDescribeSecurityGroupReferencesRequest() + request.SecurityGroupId = &securityGroupIDs + response, err = o.ecsClient.DescribeSecurityGroupReferences(request) + return +} + +func (o *ClusterUninstaller) listSecurityGroup(securityGroupIDs []string) (response *ecs.DescribeSecurityGroupsResponse, err error) { + request := ecs.CreateDescribeSecurityGroupsRequest() + securityGroupIDsString, err := json.Marshal(securityGroupIDs) + if err != nil { + return nil, err + } + request.SecurityGroupIds = string(securityGroupIDsString) + response, err = o.ecsClient.DescribeSecurityGroups(request) + return +} + +func (o *ClusterUninstaller) listEcsInstance(instanceIDs []string) (response *ecs.DescribeInstancesResponse, err error) { + request := ecs.CreateDescribeInstancesRequest() + instanceIDsString, err := json.Marshal(instanceIDs) + if err != nil { + return nil, err + } + request.InstanceIds = string(instanceIDsString) + response, err = o.ecsClient.DescribeInstances(request) + return +} + +func (o *ClusterUninstaller) modifyDeletionProtection(instanceID string) (err error) { + request := ecs.CreateModifyInstanceAttributeRequest() + request.InstanceId = instanceID + request.DeletionProtection = "false" + _, err = o.ecsClient.ModifyInstanceAttribute(request) + return +} + +func (o *ClusterUninstaller) modifyECSInstancesDeletionProtection(instanceIDs []string) (err error) { + response, err := o.listEcsInstance(instanceIDs) + if err != nil { + return err + } + for _, instance := range response.Instances.Instance { + if instance.DeletionProtection { + err := o.modifyDeletionProtection(instance.InstanceId) + if err != nil { + return err + } + } + } + return +} + +func (o *ClusterUninstaller) deleteEcsInstances() (err error) { + if len(o.TagResources.ecsInstances) <= 0 { + return nil + } + + var instanceIDs []string + for _, instanceArn := range o.TagResources.ecsInstances { + instanceIDs = append(instanceIDs, instanceArn.ResourceID) + } + + o.Logger.Debugf("Start to check and turn off ECS instances %q deletion protection", instanceIDs) + err = o.modifyECSInstancesDeletionProtection(instanceIDs) + if err != nil { + return err + } + + o.Logger.Debugf("Start to delete ECS instances %q", instanceIDs) + request := ecs.CreateDeleteInstancesRequest() + request.InstanceId = &instanceIDs + request.Force = "true" + _, err = o.ecsClient.DeleteInstances(request) + if err != nil { + return err + } + + err = wait.Poll( + 5*time.Second, + 5*time.Minute, + func() (bool, error) { + response, err := o.listEcsInstance(instanceIDs) + if err != nil { + return false, err + } + if response.TotalCount == 0 { + return true, nil + } + return false, nil + }, + ) + return +} + +func (o *ClusterUninstaller) findResourcesByTag() (tagResources []tag.TagResource, err error) { + for _, tags := range o.Tags { + resources, err := o.listTagResources(tags) + if err != nil { + return nil, err + } + tagResources = append(tagResources, resources...) + } + return tagResources, nil +} + +func (o *ClusterUninstaller) listTagResources(tags map[string]string) (tagResources []tag.TagResource, err error) { + tagsString, err := json.Marshal(tags) + if err != nil { + return nil, err + } + + o.Logger.Debugf("Retrieving cloud resources by tag %s", tagsString) + + request := tag.CreateListTagResourcesRequest() + request.PageSize = "1000" + request.Tags = string(tagsString) + request.Category = "Custom" + response, err := o.tagClient.ListTagResources(request) + if err != nil { + return nil, err + } + return response.TagResources, nil +} + +func (o *ClusterUninstaller) unTagResource(keys *[]string, arns *[]string) (err error) { + o.Logger.Debugf("Untag cloud resources %q with tags %q", arns, keys) + request := tag.CreateUntagResourcesRequest() + request.TagKey = keys + request.ResourceARN = arns + _, err = o.tagClient.UntagResources(request) + return +} + +func (o *ClusterUninstaller) deleteRAMRoles() (err error) { + roles := []string{"bootstrap", "master", "worker"} + + for _, role := range roles { + roleName := fmt.Sprintf("%s-role-%s", o.InfraID, role) + policyName := fmt.Sprintf("%s-policy-%s", o.InfraID, role) + + err = o.detachRAMPolicy(policyName) + if err != nil { + return err + } + err = o.deletePolicyByName(policyName) + if err != nil { + return err + } + err = o.deleteRAMRole(roleName) + if err != nil && !strings.Contains(err.Error(), "EntityNotExist.Role") { + return err + } + } + return nil +} + +func (o *ClusterUninstaller) deleteRAMRole(roleName string) (err error) { + o.Logger.Debugf("Start to search and delete RAM role %q", roleName) + request := ram.CreateDeleteRoleRequest() + request.Scheme = "https" + request.RoleName = roleName + _, err = o.ramClient.DeleteRole(request) + return +} + +func (o *ClusterUninstaller) deletePolicyByName(policyName string) (err error) { + err = o.deletePolicy(policyName) + if err != nil && !strings.Contains(err.Error(), "EntityNotExist.Policy") { + return err + } + + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + _, err := o.getPolicy(policyName) + if err != nil { + if strings.Contains(err.Error(), "EntityNotExist.Policy") { + return true, nil + } + return false, err + } + return false, nil + }, + ) + return +} + +func (o *ClusterUninstaller) getPolicy(policyName string) (response *ram.GetPolicyResponse, err error) { + request := ram.CreateGetPolicyRequest() + request.Scheme = "https" + request.PolicyName = policyName + request.PolicyType = "Custom" + response, err = o.ramClient.GetPolicy(request) + return +} + +func (o *ClusterUninstaller) deletePolicy(policyName string) (err error) { + o.Logger.Debugf("Start to search and delete RAM policy %q", policyName) + request := ram.CreateDeletePolicyRequest() + request.Scheme = "https" + request.PolicyName = policyName + _, err = o.ramClient.DeletePolicy(request) + return +} + +func (o *ClusterUninstaller) detachRAMPolicy(policyName string) (err error) { + o.Logger.Debugf("Start to search RAM policy %q attachments", policyName) + attachmentsResponse, err := o.listPolicyAttachments(policyName) + if err != nil { + return err + } + if attachmentsResponse.TotalCount == 0 { + return nil + } + + o.Logger.Debugf("Start to detach RAM policy %q", policyName) + for _, a := range attachmentsResponse.PolicyAttachments.PolicyAttachment { + err = o.detachPolicy(a.PolicyName, a.PolicyType, a.PrincipalName, a.PrincipalType, a.ResourceGroupId) + if err != nil { + return err + } + } + + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + attachmentsResponse, err = o.listPolicyAttachments(policyName) + if err != nil { + return false, err + } + if attachmentsResponse.TotalCount == 0 { + return true, nil + } + return false, nil + }, + ) + return +} + +func (o *ClusterUninstaller) listPolicyAttachments(policyName string) (response *resourcemanager.ListPolicyAttachmentsResponse, err error) { + request := resourcemanager.CreateListPolicyAttachmentsRequest() + request.Scheme = "https" + request.PolicyName = policyName + response, err = o.rmanagerClient.ListPolicyAttachments(request) + if err != nil { + return nil, err + } + return response, nil +} + +func (o *ClusterUninstaller) detachPolicy(policyName string, policyType string, principalName string, principalType string, resourceGroupID string) (err error) { + o.Logger.Debugf("Start to detach RAM policy %q with %q", policyName, principalName) + request := resourcemanager.CreateDetachPolicyRequest() + request.Scheme = "https" + request.PolicyName = policyName + request.PolicyType = policyType + request.PrincipalName = principalName + request.PrincipalType = principalType + request.ResourceGroupId = resourceGroupID + _, err = o.rmanagerClient.DetachPolicy(request) + return +} + +func (o *ClusterUninstaller) deletePrivateZones() (err error) { + clusterDomain := o.ClusterDomain + o.Logger.Debug("Start to search private zones") + zones, err := o.listPrivateZone(clusterDomain) + if err != nil { + return err + } + if len(zones) == 0 { + return nil + } + if len(zones) > 1 { + return errors.Wrap(err, fmt.Sprintf("matched to multiple private zones by clustedomain %q", clusterDomain)) + } + + zoneID := zones[0].ZoneId + err = o.bindZoneVpc(zoneID) + if err != nil { + return err + } + + // Wait for unbind vpc to complete + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + zones, err := o.listPrivateZone(clusterDomain) + if err != nil { + return false, err + } + + if len(zones[0].Vpcs.Vpc) == 0 { + return true, nil + } + return false, nil + }, + ) + if err != nil { + return + } + + o.Logger.Debug("Start to delete private zones") + // Delete a private zone does not require delete the record in advance + err = o.deletePrivateZone(zoneID) + if err != nil { + return err + } + + // Wait for deletion private zone to complete + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + zones, err := o.listPrivateZone(clusterDomain) + if err != nil { + return false, err + } + + if len(zones) == 0 { + return true, nil + } + return false, nil + }, + ) + if err != nil { + return err + } + + return nil +} + +func (o *ClusterUninstaller) deletePrivateZone(zoneID string) (err error) { + o.Logger.Debugf("Start to delete private zone %q", zoneID) + request := pvtz.CreateDeleteZoneRequest() + request.ZoneId = zoneID + _, err = o.pvtzClient.DeleteZone(request) + return +} + +func (o *ClusterUninstaller) bindZoneVpc(zoneID string) (err error) { + o.Logger.Debugf("Start to unbind/bind private zone %q with vpc", zoneID) + request := pvtz.CreateBindZoneVpcRequest() + request.ZoneId = zoneID + _, err = o.pvtzClient.BindZoneVpc(request) + return +} + +func (o *ClusterUninstaller) listPrivateZone(clusterDomain string) ([]pvtz.Zone, error) { + request := pvtz.CreateDescribeZonesRequest() + request.Lang = "en" + request.Keyword = clusterDomain + request.SearchMode = "EXACT" + + response, err := o.pvtzClient.DescribeZones(request) + if err != nil { + return nil, err + } + return response.Zones.Zone, nil +} + +func (o *ClusterUninstaller) deleteDNSRecords() (err error) { + o.Logger.Debug("Start to search DNS records") + + // Get the base domain from the cluster domain. the format of cluster domain is '.'. + baseDomain := strings.Join(strings.Split(o.ClusterDomain, ".")[1:], ".") + domains, err := o.listDomain(baseDomain) + if err != nil { + return + } + if len(domains) == 0 { + return + } + + records, err := o.listRecord(baseDomain) + if err != nil { + return + } + if len(records) == 0 { + return + } + + o.Logger.Debug("Start to delete DNS records") + for _, record := range records { + err = o.deleteRecord(record.RecordId) + if err != nil { + err = errors.Wrap(err, fmt.Sprintf("DNS record %q", record.RecordId)) + o.Logger.Info(err) + return + } + } + + // Wait for deletion to complete + err = wait.Poll( + 1*time.Second, + 1*time.Minute, + func() (bool, error) { + records, err := o.listRecord(baseDomain) + if err != nil { + return false, err + } + + if len(records) == 0 { + return true, nil + } + return false, nil + }, + ) + if err != nil { + return err + } + + return nil +} + +func (o *ClusterUninstaller) deleteRecord(recordID string) error { + o.Logger.Debugf("Start to delete DNS record %q", recordID) + request := alidns.CreateDeleteDomainRecordRequest() + request.Scheme = "https" + request.RecordId = recordID + _, err := o.dnsClient.DeleteDomainRecord(request) + if err != nil { + return err + } + return nil +} + +func (o *ClusterUninstaller) listDomain(baseDomain string) ([]alidns.DomainInDescribeDomains, error) { + request := alidns.CreateDescribeDomainsRequest() + request.Scheme = "https" + request.KeyWord = baseDomain + request.SearchMode = "EXACT" + response, err := o.dnsClient.DescribeDomains(request) + if err != nil { + return nil, err + } + return response.Domains.Domain, nil +} + +func (o *ClusterUninstaller) listRecord(baseDomain string) ([]alidns.Record, error) { + request := alidns.CreateDescribeDomainRecordsRequest() + request.Scheme = "https" + request.DomainName = baseDomain + response, err := o.dnsClient.DescribeDomainRecords(request) + if err != nil { + return nil, err + } + return response.DomainRecords.Record, nil +} + +func convertResourceArn(arn string) (resourceArn ResourceArn, err error) { + _arn := strings.Split(arn, "/") + serviceInfos := strings.Split(_arn[0], ":") + + resourceArn.Service = serviceInfos[2] + resourceArn.Region = serviceInfos[3] + resourceArn.Account = serviceInfos[4] + resourceArn.ResourceType = serviceInfos[5] + resourceArn.ResourceID = _arn[1] + resourceArn.Arn = arn + return resourceArn, nil +} diff --git a/pkg/destroy/alibabacloud/doc.go b/pkg/destroy/alibabacloud/doc.go new file mode 100644 index 00000000000..06b5848dd01 --- /dev/null +++ b/pkg/destroy/alibabacloud/doc.go @@ -0,0 +1,2 @@ +// Package alibabacloud provides a cluster-destroyer for Alibaba Cloud clusters. +package alibabacloud diff --git a/pkg/destroy/alibabacloud/register.go b/pkg/destroy/alibabacloud/register.go new file mode 100644 index 00000000000..bbbc0f9031a --- /dev/null +++ b/pkg/destroy/alibabacloud/register.go @@ -0,0 +1,7 @@ +package alibabacloud + +import "github.com/openshift/installer/pkg/destroy/providers" + +func init() { + providers.Registry["alibabacloud"] = New +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/client.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/client.go new file mode 100644 index 00000000000..98ffcac2f39 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/client.go @@ -0,0 +1,129 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "reflect" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider" +) + +// Client is the sdk client struct, each func corresponds to an OpenAPI +type Client struct { + sdk.Client +} + +// SetClientProperty Set Property by Reflect +func SetClientProperty(client *Client, propertyName string, propertyValue interface{}) { + v := reflect.ValueOf(client).Elem() + if v.FieldByName(propertyName).IsValid() && v.FieldByName(propertyName).CanSet() { + v.FieldByName(propertyName).Set(reflect.ValueOf(propertyValue)) + } +} + +// SetEndpointDataToClient Set EndpointMap and ENdpointType +func SetEndpointDataToClient(client *Client) { + SetClientProperty(client, "EndpointMap", GetEndpointMap()) + SetClientProperty(client, "EndpointType", GetEndpointType()) +} + +// NewClient creates a sdk client with environment variables +func NewClient() (client *Client, err error) { + client = &Client{} + err = client.Init() + SetEndpointDataToClient(client) + return +} + +// NewClientWithProvider creates a sdk client with providers +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithProvider(regionId string, providers ...provider.Provider) (client *Client, err error) { + client = &Client{} + var pc provider.Provider + if len(providers) == 0 { + pc = provider.DefaultChain + } else { + pc = provider.NewProviderChain(providers) + } + err = client.InitWithProviderChain(regionId, pc) + SetEndpointDataToClient(client) + return +} + +// NewClientWithOptions creates a sdk client with regionId/sdkConfig/credential +// this is the common api to create a sdk client +func NewClientWithOptions(regionId string, config *sdk.Config, credential auth.Credential) (client *Client, err error) { + client = &Client{} + err = client.InitWithOptions(regionId, config, credential) + SetEndpointDataToClient(client) + return +} + +// NewClientWithAccessKey is a shortcut to create sdk client with accesskey +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithAccessKey(regionId, accessKeyId, accessKeySecret string) (client *Client, err error) { + client = &Client{} + err = client.InitWithAccessKey(regionId, accessKeyId, accessKeySecret) + SetEndpointDataToClient(client) + return +} + +// NewClientWithStsToken is a shortcut to create sdk client with sts token +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken string) (client *Client, err error) { + client = &Client{} + err = client.InitWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken) + SetEndpointDataToClient(client) + return +} + +// NewClientWithRamRoleArn is a shortcut to create sdk client with ram roleArn +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithRamRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) { + client = &Client{} + err = client.InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName) + SetEndpointDataToClient(client) + return +} + +// NewClientWithRamRoleArn is a shortcut to create sdk client with ram roleArn and policy +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithRamRoleArnAndPolicy(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string) (client *Client, err error) { + client = &Client{} + err = client.InitWithRamRoleArnAndPolicy(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy) + SetEndpointDataToClient(client) + return +} + +// NewClientWithEcsRamRole is a shortcut to create sdk client with ecs ram role +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithEcsRamRole(regionId string, roleName string) (client *Client, err error) { + client = &Client{} + err = client.InitWithEcsRamRole(regionId, roleName) + SetEndpointDataToClient(client) + return +} + +// NewClientWithRsaKeyPair is a shortcut to create sdk client with rsa key pair +// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md +func NewClientWithRsaKeyPair(regionId string, publicKeyId, privateKey string, sessionExpiration int) (client *Client, err error) { + client = &Client{} + err = client.InitWithRsaKeyPair(regionId, publicKeyId, privateKey, sessionExpiration) + SetEndpointDataToClient(client) + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/endpoint.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/endpoint.go new file mode 100644 index 00000000000..516fad65cee --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/endpoint.go @@ -0,0 +1,63 @@ +package tag + +// EndpointMap Endpoint Data +var EndpointMap map[string]string + +// EndpointType regional or central +var EndpointType = "regional" + +// GetEndpointMap Get Endpoint Data Map +func GetEndpointMap() map[string]string { + if EndpointMap == nil { + EndpointMap = map[string]string{ + "cn-shanghai-internal-test-1": "tag.aliyuncs.com", + "cn-beijing-gov-1": "tag.aliyuncs.com", + "cn-shenzhen-su18-b01": "tag.aliyuncs.com", + "cn-beijing": "tag.aliyuncs.com", + "cn-shanghai-inner": "tag.aliyuncs.com", + "cn-shenzhen-st4-d01": "tag.aliyuncs.com", + "cn-haidian-cm12-c01": "tag.aliyuncs.com", + "cn-hangzhou-internal-prod-1": "tag.aliyuncs.com", + "cn-yushanfang": "tag.aliyuncs.com", + "cn-qingdao": "tag.aliyuncs.com", + "cn-hongkong-finance-pop": "tag.aliyuncs.com", + "cn-qingdao-nebula": "tag.aliyuncs.com", + "cn-shanghai": "tag.aliyuncs.com", + "cn-shanghai-finance-1": "tag.aliyuncs.com", + "cn-hongkong": "tag.aliyuncs.com", + "cn-beijing-finance-pop": "tag.aliyuncs.com", + "cn-wuhan": "tag.aliyuncs.com", + "us-west-1": "tag.aliyuncs.com", + "cn-shenzhen": "tag.aliyuncs.com", + "cn-zhengzhou-nebula-1": "tag.aliyuncs.com", + "rus-west-1-pop": "tag.aliyuncs.com", + "cn-shanghai-et15-b01": "tag.aliyuncs.com", + "cn-hangzhou-bj-b01": "tag.aliyuncs.com", + "cn-hangzhou-internal-test-1": "tag.aliyuncs.com", + "eu-west-1-oxs": "tag.cn-shenzhen-cloudstone.aliyuncs.com", + "cn-zhangbei-na61-b01": "tag.aliyuncs.com", + "cn-beijing-finance-1": "tag.aliyuncs.com", + "cn-hangzhou-internal-test-3": "tag.aliyuncs.com", + "cn-hangzhou-internal-test-2": "tag.aliyuncs.com", + "cn-shenzhen-finance-1": "tag.aliyuncs.com", + "cn-hangzhou-test-306": "tag.aliyuncs.com", + "cn-shanghai-et2-b01": "tag.aliyuncs.com", + "cn-hangzhou-finance": "tag.aliyuncs.com", + "ap-southeast-1": "tag.aliyuncs.com", + "cn-beijing-nu16-b01": "tag.aliyuncs.com", + "cn-edge-1": "tag.aliyuncs.com", + "us-east-1": "tag.aliyuncs.com", + "cn-fujian": "tag.aliyuncs.com", + "ap-northeast-2-pop": "tag.aliyuncs.com", + "cn-shenzhen-inner": "tag.aliyuncs.com", + "cn-zhangjiakou-na62-a01": "tag.aliyuncs.com", + "cn-hangzhou": "tag.aliyuncs.com", + } + } + return EndpointMap +} + +// GetEndpointType Get Endpoint Type Value +func GetEndpointType() string { + return EndpointType +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_keys.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_keys.go new file mode 100644 index 00000000000..06f10e4b725 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_keys.go @@ -0,0 +1,107 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// ListTagKeys invokes the tag.ListTagKeys API synchronously +func (client *Client) ListTagKeys(request *ListTagKeysRequest) (response *ListTagKeysResponse, err error) { + response = CreateListTagKeysResponse() + err = client.DoAction(request, response) + return +} + +// ListTagKeysWithChan invokes the tag.ListTagKeys API asynchronously +func (client *Client) ListTagKeysWithChan(request *ListTagKeysRequest) (<-chan *ListTagKeysResponse, <-chan error) { + responseChan := make(chan *ListTagKeysResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.ListTagKeys(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// ListTagKeysWithCallback invokes the tag.ListTagKeys API asynchronously +func (client *Client) ListTagKeysWithCallback(request *ListTagKeysRequest, callback func(response *ListTagKeysResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *ListTagKeysResponse + var err error + defer close(result) + response, err = client.ListTagKeys(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// ListTagKeysRequest is the request struct for api ListTagKeys +type ListTagKeysRequest struct { + *requests.RpcRequest + NextToken string `position:"Query" name:"NextToken"` + PageSize requests.Integer `position:"Query" name:"PageSize"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerAccount string `position:"Query" name:"OwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + ResourceType string `position:"Query" name:"ResourceType"` + Category string `position:"Query" name:"Category"` +} + +// ListTagKeysResponse is the response struct for api ListTagKeys +type ListTagKeysResponse struct { + *responses.BaseResponse + NextToken string `json:"NextToken" xml:"NextToken"` + RequestId string `json:"RequestId" xml:"RequestId"` + Keys Keys `json:"Keys" xml:"Keys"` +} + +// CreateListTagKeysRequest creates a request to invoke ListTagKeys API +func CreateListTagKeysRequest() (request *ListTagKeysRequest) { + request = &ListTagKeysRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Tag", "2018-08-28", "ListTagKeys", "tag", "openAPI") + request.Method = requests.POST + return +} + +// CreateListTagKeysResponse creates a response to parse from ListTagKeys response +func CreateListTagKeysResponse() (response *ListTagKeysResponse) { + response = &ListTagKeysResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_resources.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_resources.go new file mode 100644 index 00000000000..4765862ced0 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_resources.go @@ -0,0 +1,108 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// ListTagResources invokes the tag.ListTagResources API synchronously +func (client *Client) ListTagResources(request *ListTagResourcesRequest) (response *ListTagResourcesResponse, err error) { + response = CreateListTagResourcesResponse() + err = client.DoAction(request, response) + return +} + +// ListTagResourcesWithChan invokes the tag.ListTagResources API asynchronously +func (client *Client) ListTagResourcesWithChan(request *ListTagResourcesRequest) (<-chan *ListTagResourcesResponse, <-chan error) { + responseChan := make(chan *ListTagResourcesResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.ListTagResources(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// ListTagResourcesWithCallback invokes the tag.ListTagResources API asynchronously +func (client *Client) ListTagResourcesWithCallback(request *ListTagResourcesRequest, callback func(response *ListTagResourcesResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *ListTagResourcesResponse + var err error + defer close(result) + response, err = client.ListTagResources(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// ListTagResourcesRequest is the request struct for api ListTagResources +type ListTagResourcesRequest struct { + *requests.RpcRequest + NextToken string `position:"Query" name:"NextToken"` + PageSize requests.Integer `position:"Query" name:"PageSize"` + ResourceARN *[]string `position:"Query" name:"ResourceARN" type:"Repeated"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerAccount string `position:"Query" name:"OwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + Tags string `position:"Query" name:"Tags"` + Category string `position:"Query" name:"Category"` +} + +// ListTagResourcesResponse is the response struct for api ListTagResources +type ListTagResourcesResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + NextToken string `json:"NextToken" xml:"NextToken"` + TagResources []TagResource `json:"TagResources" xml:"TagResources"` +} + +// CreateListTagResourcesRequest creates a request to invoke ListTagResources API +func CreateListTagResourcesRequest() (request *ListTagResourcesRequest) { + request = &ListTagResourcesRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Tag", "2018-08-28", "ListTagResources", "tag", "openAPI") + request.Method = requests.POST + return +} + +// CreateListTagResourcesResponse creates a response to parse from ListTagResources response +func CreateListTagResourcesResponse() (response *ListTagResourcesResponse) { + response = &ListTagResourcesResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_values.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_values.go new file mode 100644 index 00000000000..273d6cfdde8 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/list_tag_values.go @@ -0,0 +1,107 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// ListTagValues invokes the tag.ListTagValues API synchronously +func (client *Client) ListTagValues(request *ListTagValuesRequest) (response *ListTagValuesResponse, err error) { + response = CreateListTagValuesResponse() + err = client.DoAction(request, response) + return +} + +// ListTagValuesWithChan invokes the tag.ListTagValues API asynchronously +func (client *Client) ListTagValuesWithChan(request *ListTagValuesRequest) (<-chan *ListTagValuesResponse, <-chan error) { + responseChan := make(chan *ListTagValuesResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.ListTagValues(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// ListTagValuesWithCallback invokes the tag.ListTagValues API asynchronously +func (client *Client) ListTagValuesWithCallback(request *ListTagValuesRequest, callback func(response *ListTagValuesResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *ListTagValuesResponse + var err error + defer close(result) + response, err = client.ListTagValues(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// ListTagValuesRequest is the request struct for api ListTagValues +type ListTagValuesRequest struct { + *requests.RpcRequest + NextToken string `position:"Query" name:"NextToken"` + PageSize requests.Integer `position:"Query" name:"PageSize"` + Key string `position:"Query" name:"Key"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerAccount string `position:"Query" name:"OwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + ResourceType string `position:"Query" name:"ResourceType"` +} + +// ListTagValuesResponse is the response struct for api ListTagValues +type ListTagValuesResponse struct { + *responses.BaseResponse + NextToken string `json:"NextToken" xml:"NextToken"` + RequestId string `json:"RequestId" xml:"RequestId"` + Values Values `json:"Values" xml:"Values"` +} + +// CreateListTagValuesRequest creates a request to invoke ListTagValues API +func CreateListTagValuesRequest() (request *ListTagValuesRequest) { + request = &ListTagValuesRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Tag", "2018-08-28", "ListTagValues", "tag", "openAPI") + request.Method = requests.POST + return +} + +// CreateListTagValuesResponse creates a response to parse from ListTagValues response +func CreateListTagValuesResponse() (response *ListTagValuesResponse) { + response = &ListTagValuesResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resource.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resource.go new file mode 100644 index 00000000000..99b9c285610 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resource.go @@ -0,0 +1,22 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// FailedResource is a nested struct in tag response +type FailedResource struct { + ResourceARN string `json:"ResourceARN" xml:"ResourceARN"` + Result Result `json:"Result" xml:"Result"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resources_in_tag_resources.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resources_in_tag_resources.go new file mode 100644 index 00000000000..b6916bbf735 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resources_in_tag_resources.go @@ -0,0 +1,21 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// FailedResourcesInTagResources is a nested struct in tag response +type FailedResourcesInTagResources struct { + FailedResource []FailedResource `json:"FailedResource" xml:"FailedResource"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resources_in_untag_resources.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resources_in_untag_resources.go new file mode 100644 index 00000000000..d87816ea340 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_failed_resources_in_untag_resources.go @@ -0,0 +1,21 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// FailedResourcesInUntagResources is a nested struct in tag response +type FailedResourcesInUntagResources struct { + FailedResource []FailedResource `json:"FailedResource" xml:"FailedResource"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_key.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_key.go new file mode 100644 index 00000000000..9ae97b38c2f --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_key.go @@ -0,0 +1,22 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// Key is a nested struct in tag response +type Key struct { + Category string `json:"Category" xml:"Category"` + Key string `json:"Key" xml:"Key"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_keys.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_keys.go new file mode 100644 index 00000000000..7144a4b2742 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_keys.go @@ -0,0 +1,21 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// Keys is a nested struct in tag response +type Keys struct { + Key []Key `json:"Key" xml:"Key"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_result.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_result.go new file mode 100644 index 00000000000..de9a7d5b581 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_result.go @@ -0,0 +1,22 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// Result is a nested struct in tag response +type Result struct { + Message string `json:"Message" xml:"Message"` + Code string `json:"Code" xml:"Code"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag.go new file mode 100644 index 00000000000..26ce2ed6d1f --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag.go @@ -0,0 +1,23 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// Tag is a nested struct in tag response +type Tag struct { + Key string `json:"Key" xml:"Key"` + Value string `json:"Value" xml:"Value"` + Category string `json:"Category" xml:"Category"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag_resource.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag_resource.go new file mode 100644 index 00000000000..f45baf790a9 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag_resource.go @@ -0,0 +1,22 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// TagResource is a nested struct in tag response +type TagResource struct { + ResourceARN string `json:"ResourceARN" xml:"ResourceARN"` + Tags []Tag `json:"Tags" xml:"Tags"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag_resources.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag_resources.go new file mode 100644 index 00000000000..4a03892bcd0 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tag_resources.go @@ -0,0 +1,21 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// TagResources is a nested struct in tag response +type TagResources struct { + TagResource []TagResource `json:"TagResource" xml:"TagResource"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tags.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tags.go new file mode 100644 index 00000000000..df4e0123371 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_tags.go @@ -0,0 +1,21 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// Tags is a nested struct in tag response +type Tags struct { + Tag []Tag `json:"Tag" xml:"Tag"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_values.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_values.go new file mode 100644 index 00000000000..455d2ef52bf --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/struct_values.go @@ -0,0 +1,21 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// Values is a nested struct in tag response +type Values struct { + Value []string `json:"Value" xml:"Value"` +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/tag_resources.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/tag_resources.go new file mode 100644 index 00000000000..6762245bef3 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/tag_resources.go @@ -0,0 +1,104 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// TagResources invokes the tag.TagResources API synchronously +func (client *Client) TagResources(request *TagResourcesRequest) (response *TagResourcesResponse, err error) { + response = CreateTagResourcesResponse() + err = client.DoAction(request, response) + return +} + +// TagResourcesWithChan invokes the tag.TagResources API asynchronously +func (client *Client) TagResourcesWithChan(request *TagResourcesRequest) (<-chan *TagResourcesResponse, <-chan error) { + responseChan := make(chan *TagResourcesResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.TagResources(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// TagResourcesWithCallback invokes the tag.TagResources API asynchronously +func (client *Client) TagResourcesWithCallback(request *TagResourcesRequest, callback func(response *TagResourcesResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *TagResourcesResponse + var err error + defer close(result) + response, err = client.TagResources(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// TagResourcesRequest is the request struct for api TagResources +type TagResourcesRequest struct { + *requests.RpcRequest + ResourceARN *[]string `position:"Query" name:"ResourceARN" type:"Repeated"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerAccount string `position:"Query" name:"OwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + Tags string `position:"Query" name:"Tags"` +} + +// TagResourcesResponse is the response struct for api TagResources +type TagResourcesResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + FailedResources FailedResourcesInTagResources `json:"FailedResources" xml:"FailedResources"` +} + +// CreateTagResourcesRequest creates a request to invoke TagResources API +func CreateTagResourcesRequest() (request *TagResourcesRequest) { + request = &TagResourcesRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Tag", "2018-08-28", "TagResources", "tag", "openAPI") + request.Method = requests.POST + return +} + +// CreateTagResourcesResponse creates a response to parse from TagResources response +func CreateTagResourcesResponse() (response *TagResourcesResponse) { + response = &TagResourcesResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/untag_resources.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/untag_resources.go new file mode 100644 index 00000000000..fc76ba0ac98 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/tag/untag_resources.go @@ -0,0 +1,104 @@ +package tag + +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +// +// Code generated by Alibaba Cloud SDK Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" +) + +// UntagResources invokes the tag.UntagResources API synchronously +func (client *Client) UntagResources(request *UntagResourcesRequest) (response *UntagResourcesResponse, err error) { + response = CreateUntagResourcesResponse() + err = client.DoAction(request, response) + return +} + +// UntagResourcesWithChan invokes the tag.UntagResources API asynchronously +func (client *Client) UntagResourcesWithChan(request *UntagResourcesRequest) (<-chan *UntagResourcesResponse, <-chan error) { + responseChan := make(chan *UntagResourcesResponse, 1) + errChan := make(chan error, 1) + err := client.AddAsyncTask(func() { + defer close(responseChan) + defer close(errChan) + response, err := client.UntagResources(request) + if err != nil { + errChan <- err + } else { + responseChan <- response + } + }) + if err != nil { + errChan <- err + close(responseChan) + close(errChan) + } + return responseChan, errChan +} + +// UntagResourcesWithCallback invokes the tag.UntagResources API asynchronously +func (client *Client) UntagResourcesWithCallback(request *UntagResourcesRequest, callback func(response *UntagResourcesResponse, err error)) <-chan int { + result := make(chan int, 1) + err := client.AddAsyncTask(func() { + var response *UntagResourcesResponse + var err error + defer close(result) + response, err = client.UntagResources(request) + callback(response, err) + result <- 1 + }) + if err != nil { + defer close(result) + callback(nil, err) + result <- 0 + } + return result +} + +// UntagResourcesRequest is the request struct for api UntagResources +type UntagResourcesRequest struct { + *requests.RpcRequest + ResourceARN *[]string `position:"Query" name:"ResourceARN" type:"Repeated"` + ResourceOwnerAccount string `position:"Query" name:"ResourceOwnerAccount"` + OwnerAccount string `position:"Query" name:"OwnerAccount"` + OwnerId requests.Integer `position:"Query" name:"OwnerId"` + TagKey *[]string `position:"Query" name:"TagKey" type:"Repeated"` +} + +// UntagResourcesResponse is the response struct for api UntagResources +type UntagResourcesResponse struct { + *responses.BaseResponse + RequestId string `json:"RequestId" xml:"RequestId"` + FailedResources FailedResourcesInUntagResources `json:"FailedResources" xml:"FailedResources"` +} + +// CreateUntagResourcesRequest creates a request to invoke UntagResources API +func CreateUntagResourcesRequest() (request *UntagResourcesRequest) { + request = &UntagResourcesRequest{ + RpcRequest: &requests.RpcRequest{}, + } + request.InitWithApiInfo("Tag", "2018-08-28", "UntagResources", "tag", "openAPI") + request.Method = requests.POST + return +} + +// CreateUntagResourcesResponse creates a response to parse from UntagResources response +func CreateUntagResourcesResponse() (response *UntagResourcesResponse) { + response = &UntagResourcesResponse{ + BaseResponse: &responses.BaseResponse{}, + } + return +} diff --git a/vendor/modules.txt b/vendor/modules.txt index c3e192a1b67..c8964455c65 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -486,6 +486,7 @@ github.com/aliyun/alibaba-cloud-sdk-go/services/slb github.com/aliyun/alibaba-cloud-sdk-go/services/sls github.com/aliyun/alibaba-cloud-sdk-go/services/smartag github.com/aliyun/alibaba-cloud-sdk-go/services/sts +github.com/aliyun/alibaba-cloud-sdk-go/services/tag github.com/aliyun/alibaba-cloud-sdk-go/services/vpc github.com/aliyun/alibaba-cloud-sdk-go/services/yundun_bastionhost github.com/aliyun/alibaba-cloud-sdk-go/services/yundun_dbaudit