feature(region): support AWS organization

This commit is contained in:
Qiu Jian
2021-02-19 02:25:37 +08:00
parent 7ee11117c5
commit 2da59aa89f
31 changed files with 25164 additions and 179 deletions
+2
View File
@@ -32,6 +32,7 @@ type BaseOptions struct {
AccessKey string `help:"Access key" default:"$AWS_ACCESS_KEY" metavar:"AWS_ACCESS_KEY"`
Secret string `help:"Secret" default:"$AWS_SECRET" metavar:"AWS_SECRET"`
RegionId string `help:"RegionId" default:"$AWS_REGION" metavar:"AWS_REGION"`
AccountId string `help:"Subaccount ID" default:"$AWS_ACCOUNT_ID" metavar:"AWS_ACCOUNT_ID"`
SUBCOMMAND string `help:"awscli subcommand" subcommand:"true"`
}
@@ -90,6 +91,7 @@ func newClient(options *BaseOptions) (*aws.SRegion, error) {
options.AccessUrl,
options.AccessKey,
options.Secret,
options.AccountId,
).Debug(options.Debug),
)
if err != nil {
+2 -2
View File
@@ -150,9 +150,9 @@ require (
yunion.io/x/jsonutils v0.0.0-20201110084044-3e4e1cb49769
yunion.io/x/log v0.0.0-20201210064738-43181789dc74
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
yunion.io/x/pkg v0.0.0-20210109071527-7e72daf56747
yunion.io/x/pkg v0.0.0-20210218105412-13a69f60034c
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb
yunion.io/x/sqlchemy v0.0.0-20210204030051-4fb14f92a88f
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce
)
+4 -4
View File
@@ -924,11 +924,11 @@ yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7/go.mod h1:0vLkNEhlmA64HViPB
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20200814072949-4f1b541857d6/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20210109071527-7e72daf56747 h1:sTr6mjWW8aAMKkrnnU2SG8EqhLRl/D3rGnBhaP2ksTI=
yunion.io/x/pkg v0.0.0-20210109071527-7e72daf56747/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20210218105412-13a69f60034c h1:J/joqbA1N2mAlOl0Uqd4LpAq3+DK5aoFMdz+p9Ld7pQ=
yunion.io/x/pkg v0.0.0-20210218105412-13a69f60034c/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb h1:k7s5xMCd/fw29vUaNsGCrLkyn7w8eSghJ5NChuU9SAk=
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/sqlchemy v0.0.0-20210204030051-4fb14f92a88f h1:RH3RY/AReFPwASyakFnHyFaHb0N+juxWmwiPlOHZqaY=
yunion.io/x/sqlchemy v0.0.0-20210204030051-4fb14f92a88f/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce h1:kU8xE7O5uZ1GSJVMZHoJ+jrNL7csUQHYGyAPW9QfNpE=
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
+13 -8
View File
@@ -946,7 +946,7 @@ func (self *SCloudaccount) importSubAccount(ctx context.Context, userCred mcclie
if err != nil {
return nil, isNew, err
}
provider.markProviderConnected(ctx, userCred, self.HealthStatus)
provider.markProviderConnected(ctx, userCred, subAccount.HealthStatus)
return provider, isNew, nil
}
// not found, create a new cloudprovider
@@ -966,12 +966,17 @@ func (self *SCloudaccount) importSubAccount(ctx context.Context, userCred mcclie
newCloudprovider.CloudaccountId = self.Id
newCloudprovider.Provider = self.Provider
newCloudprovider.AccessUrl = self.AccessUrl
newCloudprovider.SetEnabled(true)
newCloudprovider.Status = api.CLOUD_PROVIDER_CONNECTED
newCloudprovider.HealthStatus = subAccount.HealthStatus
if !options.Options.CloudaccountHealthStatusCheck {
self.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
newCloudprovider.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
}
if newCloudprovider.HealthStatus == api.CLOUD_PROVIDER_HEALTH_NORMAL {
newCloudprovider.SetEnabled(true)
newCloudprovider.Status = api.CLOUD_PROVIDER_CONNECTED
} else {
newCloudprovider.SetEnabled(false)
newCloudprovider.Status = api.CLOUD_PROVIDER_DISCONNECTED
}
newCloudprovider.HealthStatus = self.HealthStatus
newCloudprovider.Name = newName
if !self.AutoCreateProject || len(self.ProjectId) > 0 {
ownerId := self.GetOwnerId()
@@ -1926,9 +1931,9 @@ func (account *SCloudaccount) probeAccountStatus(ctx context.Context, userCred m
if !options.Options.CloudaccountHealthStatusCheck {
status = api.CLOUD_PROVIDER_HEALTH_NORMAL
}
if len(account.AccountId) == 0 {
account.AccountId = manager.GetAccountId()
}
// if len(account.AccountId) == 0 || account.AccountId != manager.GetAccountId() {
account.AccountId = manager.GetAccountId()
// }
account.HealthStatus = status
account.ProbeAt = timeutils.UtcNow()
account.Version = version
+85 -35
View File
@@ -17,6 +17,7 @@ package aws
import (
"fmt"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
sdk "github.com/aws/aws-sdk-go/aws"
@@ -25,6 +26,7 @@ import (
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/corehandlers"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
@@ -69,15 +71,17 @@ type AwsClientConfig struct {
accessUrl string // 服务区域 ChinaCloud | InternationalCloud
accessKey string
accessSecret string
accountId string
debug bool
}
func NewAwsClientConfig(accessUrl, accessKey, accessSecret string) *AwsClientConfig {
func NewAwsClientConfig(accessUrl, accessKey, accessSecret, accountId string) *AwsClientConfig {
cfg := &AwsClientConfig{
accessUrl: accessUrl,
accessKey: accessKey,
accessSecret: accessSecret,
accountId: accountId,
}
return cfg
}
@@ -101,6 +105,8 @@ type SAwsClient struct {
iregions []cloudprovider.ICloudRegion
iBuckets []cloudprovider.ICloudBucket
sessions map[string]*session.Session
}
func NewAwsClient(cfg *AwsClientConfig) (*SAwsClient, error) {
@@ -111,9 +117,9 @@ func NewAwsClient(cfg *AwsClientConfig) (*SAwsClient, error) {
if err != nil {
return nil, errors.Wrap(err, "fetchRegions")
}
err = client.fetchBuckets()
err = client.fetchOwnerId()
if err != nil {
return nil, errors.Wrap(err, "fetchBuckets")
return nil, errors.Wrap(err, "fetchOwnerId")
}
if client.debug {
log.Debugf("ownerId: %s ownerName: %s", client.ownerId, client.ownerName)
@@ -159,23 +165,11 @@ func (client *SAwsClient) getDefaultSession() (*session.Session, error) {
return client.getAwsSession(client.getDefaultRegionId())
}
func (self *SAwsClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
// todo: implement me
err := self.fetchRegions()
if err != nil {
return nil, errors.Wrap(err, "fetchRegions")
}
subAccount := cloudprovider.SSubAccount{}
subAccount.Name = self.cpcfg.Name
subAccount.Account = self.accessKey
subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
return []cloudprovider.SSubAccount{subAccount}, nil
}
func (client *SAwsClient) GetAccountId() string {
return client.ownerId
}
/*
func (self *SAwsClient) UpdateAccount(accessKey, secret string) error {
if self.accessKey != accessKey || self.accessSecret != secret {
self.accessKey = accessKey
@@ -186,35 +180,46 @@ func (self *SAwsClient) UpdateAccount(accessKey, secret string) error {
return nil
}
}
*/
var (
// cache for describeRegions
describeRegionResult *ec2.DescribeRegionsOutput
describeRegionResultCacheAt time.Time
)
const (
describeRegionExpireHours = 2
)
// 用于初始化region信息
func (self *SAwsClient) fetchRegions() error {
if self.iregions != nil {
return nil
}
s, err := self.getDefaultSession()
if err != nil {
return err
}
svc := ec2.New(s)
// https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#EC2.DescribeRegions
result, err := svc.DescribeRegions(&ec2.DescribeRegionsInput{})
if err != nil {
return err
if describeRegionResult == nil || time.Now().After(describeRegionResultCacheAt.Add(time.Second*3600*describeRegionExpireHours)) {
s, err := self.getDefaultSession()
if err != nil {
return errors.Wrap(err, "getDefaultSession")
}
svc := ec2.New(s)
// https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#EC2.DescribeRegions
result, err := svc.DescribeRegions(&ec2.DescribeRegionsInput{})
if err != nil {
return errors.Wrap(err, "DescribeRegions")
}
describeRegionResult = result
describeRegionResultCacheAt = time.Now()
}
regions := make([]SRegion, 0)
// empty iregions
// if self.iregions != nil {
// self.iregions = self.iregions[:0]
// }
for _, region := range result.Regions {
for _, region := range describeRegionResult.Regions {
name := *region.RegionName
endpoint := *region.Endpoint
sregion := SRegion{client: self, RegionId: name, RegionEndpoint: endpoint}
// 初始化region client
sregion.getEc2Client()
// sregion.getEc2Client()
regions = append(regions, sregion)
self.iregions = append(self.iregions, &sregion)
}
@@ -223,6 +228,12 @@ func (self *SAwsClient) fetchRegions() error {
}
func (client *SAwsClient) getAwsSession(regionId string) (*session.Session, error) {
if client.sessions == nil {
client.sessions = make(map[string]*session.Session)
}
if sess, ok := client.sessions[regionId]; ok {
return sess, nil
}
httpClient := client.cpcfg.AdaptiveTimeoutHttpClient()
s, err := session.NewSession(&sdk.Config{
Region: sdk.String(regionId),
@@ -236,11 +247,26 @@ func (client *SAwsClient) getAwsSession(regionId string) (*session.Session, erro
if err != nil {
return nil, errors.Wrap(err, "getAwsSession.NewSession")
}
if len(client.accountId) > 0 {
// need to assumeRole
var env string
switch client.GetAccessEnv() {
case api.CLOUD_ACCESS_ENV_AWS_GLOBAL:
env = "aws"
default:
env = "aws-cn"
}
roleARN := fmt.Sprintf("arn:%s:iam::%s:role/OrganizationAccountAccessRole", env, client.accountId)
creds := stscreds.NewCredentials(s, roleARN)
s = s.Copy(&aws.Config{Credentials: creds})
}
if client.debug {
logLevel := aws.LogLevelType(uint(aws.LogDebugWithRequestErrors) + uint(aws.LogDebugWithHTTPBody) + uint(aws.LogDebugWithSigning))
s.Config.LogLevel = &logLevel
}
return s, nil
client.sessions[regionId] = s
return client.sessions[regionId], nil
}
func (region *SRegion) getAwsElasticacheClient() (*elasticache.ElastiCache, error) {
@@ -284,8 +310,14 @@ func (self *SAwsClient) getIBuckets() ([]cloudprovider.ICloudBucket, error) {
return self.iBuckets, nil
}
func (client *SAwsClient) fetchBuckets() error {
s, err := client.getDefaultSession()
func (client *SAwsClient) fetchOwnerId() error {
ident, err := client.GetCallerIdentity()
if err != nil {
return errors.Wrap(err, "GetCallerIdentity")
}
client.ownerId = ident.Account
/* s, err := client.getDefaultSession()
if err != nil {
return errors.Wrap(err, "getDefaultSession")
}
@@ -302,6 +334,20 @@ func (client *SAwsClient) fetchBuckets() error {
if output.Owner.DisplayName != nil {
client.ownerName = *output.Owner.DisplayName
}
} */
return nil
}
func (client *SAwsClient) fetchBuckets() error {
s, err := client.getDefaultSession()
if err != nil {
return errors.Wrap(err, "getDefaultSession")
}
s3cli := s3.New(s)
output, err := s3cli.ListBuckets(&s3.ListBucketsInput{})
if err != nil {
return errors.Wrap(err, "ListBuckets")
}
ret := make([]cloudprovider.ICloudBucket, 0)
@@ -381,6 +427,10 @@ func (self *SAwsClient) GetRegion(regionId string) *SRegion {
return nil
}
func (self *SAwsClient) getDefaultRegion() *SRegion {
return self.GetRegion("")
}
func (self *SAwsClient) getIRegionByRegionId(id string) (cloudprovider.ICloudRegion, error) {
for i := 0; i < len(self.iregions); i += 1 {
if self.iregions[i].GetId() == id {
+30 -8
View File
@@ -298,9 +298,13 @@ func (self *SRegion) GetDisks(instanceId string, zoneId string, storageType stri
params.SetVolumeIds(ConvertedList(diskIds))
}
ret, err := self.ec2Client.DescribeVolumes(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, 0, err
return nil, 0, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeVolumes(params)
if err != nil {
return nil, 0, errors.Wrap(err, "DescribeVolumes")
}
disks := []SDisk{}
@@ -404,7 +408,11 @@ func (self *SRegion) DeleteDisk(diskId string) error {
params.SetVolumeId(diskId)
log.Debugf("DeleteDisk with params: %s", params.String())
_, err = self.ec2Client.DeleteVolume(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.DeleteVolume(params)
return err
}
@@ -426,7 +434,12 @@ func (self *SRegion) resizeDisk(diskId string, sizeMb int64) error {
} else {
params.SetVolumeId(diskId)
}
_, err := self.ec2Client.ModifyVolume(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.ModifyVolume(params)
return err
}
@@ -447,7 +460,12 @@ func (self *SRegion) resetDisk(diskId, snapshotId string) (string, error) {
params.SetAvailabilityZone(disk.ZoneId)
tags, _ := disk.Tags.GetTagSpecifications()
params.SetTagSpecifications([]*ec2.TagSpecification{tags})
ret, err := self.ec2Client.CreateVolume(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.CreateVolume(params)
if err != nil {
log.Debugf("resetDisk %s: %s", params.String(), err.Error())
return "", err
@@ -461,7 +479,7 @@ func (self *SRegion) resetDisk(diskId, snapshotId string) (string, error) {
return "", err
}
err = self.ec2Client.WaitUntilVolumeAvailable(&ec2.DescribeVolumesInput{VolumeIds: []*string{&diskId}})
err = ec2Client.WaitUntilVolumeAvailable(&ec2.DescribeVolumesInput{VolumeIds: []*string{&diskId}})
if err != nil {
log.Debugf("resetDisk :%s", err.Error())
return "", err
@@ -498,14 +516,18 @@ func (self *SRegion) CreateDisk(zoneId string, category string, name string, siz
params.SetTagSpecifications([]*ec2.TagSpecification{ec2Tags})
ret, err := self.ec2Client.CreateVolume(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.CreateVolume(params)
if err != nil {
return "", err
}
paramsWait := &ec2.DescribeVolumesInput{}
paramsWait.SetVolumeIds([]*string{ret.VolumeId})
err = self.ec2Client.WaitUntilVolumeAvailable(paramsWait)
err = ec2Client.WaitUntilVolumeAvailable(paramsWait)
if err != nil {
return "", err
}
+36 -9
View File
@@ -168,7 +168,11 @@ func (self *SRegion) GetEips(eipId string, eipAddress string, offset int, limit
params.SetPublicIps([]*string{&eipAddress})
}
res, err := self.ec2Client.DescribeAddresses(&params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, 0, errors.Wrap(err, "getEc2Client")
}
res, err := ec2Client.DescribeAddresses(&params)
err = parseNotFoundError(err)
if err != nil {
log.Errorf("DescribeEipAddresses fail %s", err)
@@ -242,7 +246,12 @@ func (self *SRegion) GetEipByIpAddress(eipAddress string) (*SEipAddress, error)
func (self *SRegion) AllocateEIP(domainType string) (*SEipAddress, error) {
params := &ec2.AllocateAddressInput{}
params.SetDomain(domainType)
eip, err := self.ec2Client.AllocateAddress(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
eip, err := ec2Client.AllocateAddress(params)
if err != nil {
log.Errorf("AllocateEipAddress fail %s", err)
return nil, errors.Wrap(err, "AllocateAddress")
@@ -256,6 +265,10 @@ func (self *SRegion) AllocateEIP(domainType string) (*SEipAddress, error) {
}
func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
// todo: aws 不支持指定bwMbps, chargeType
log.Debugf("CreateEip: aws not support specific params name/bwMbps/chargeType.")
ieip, err := self.AllocateEIP("vpc")
@@ -268,7 +281,7 @@ func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP
params.SetTags([]*ec2.Tag{nameTag})
// name 创建成功与否不影响eip的正常使用
if _, e := self.ec2Client.CreateTags(params); e != nil {
if _, e := ec2Client.CreateTags(params); e != nil {
log.Infof("CreateEIP create name tag failed: %s", e)
}
}
@@ -277,18 +290,26 @@ func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP
}
func (self *SRegion) DeallocateEIP(eipId string) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
params := &ec2.ReleaseAddressInput{}
params.SetAllocationId(eipId)
_, err := self.ec2Client.ReleaseAddress(params)
return err
_, err = ec2Client.ReleaseAddress(params)
return errors.Wrap(err, "ReleaseAddress")
}
func (self *SRegion) AssociateEip(eipId string, instanceId string) error {
params := &ec2.AssociateAddressInput{}
params.SetAllocationId(eipId)
params.SetInstanceId(instanceId)
_, err := self.ec2Client.AssociateAddress(params)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.AssociateAddress(params)
return errors.Wrap(err, "AssociateAddress")
}
func (self *SRegion) DissociateEip(eipId string, instanceId string) error {
@@ -308,8 +329,14 @@ func (self *SRegion) DissociateEip(eipId string, instanceId string) error {
params := &ec2.DisassociateAddressInput{}
params.SetAssociationId(eip.AssociationId)
_, err = self.ec2Client.DisassociateAddress(params)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.DisassociateAddress(params)
return errors.Wrap(err, "DisassociateAddress")
}
func (self *SRegion) UpdateEipBandwidth(eipId string, bw int) error {
+32 -8
View File
@@ -125,7 +125,11 @@ func (self *ImageImportTask) GetGlobalId() string {
}
func (self *ImageImportTask) Refresh() error {
ret, err := self.region.ec2Client.DescribeImportImageTasks(&ec2.DescribeImportImageTasksInput{ImportTaskIds: []*string{&self.TaskId}})
ec2Client, err := self.region.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeImportImageTasks(&ec2.DescribeImportImageTasksInput{ImportTaskIds: []*string{&self.TaskId}})
if err != nil {
log.Errorf("DescribeImportImageTasks %s", err)
return errors.Wrap(err, "ImageImportTask.Refresh.DescribeImportImageTasks")
@@ -317,7 +321,11 @@ func (self *SRegion) ImportImage(name string, osArch string, osType string, osDi
container.SetUserBucket(bkt)
params.SetDiskContainers([]*ec2.ImageDiskContainer{container})
params.SetLicenseType("BYOL") // todo: AWS?
ret, err := self.ec2Client.ImportImage(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.ImportImage(params)
if err != nil {
return nil, errors.Wrap(err, "ImportImage")
}
@@ -341,7 +349,11 @@ func (self *SRegion) ExportImage(instanceId string, imageId string) (*ImageExpor
spec.SetDiskImageFormat("RAW")
spec.SetS3Bucket("imgcache-onecloud")
params.SetExportToS3Task(spec)
ret, err := self.ec2Client.CreateInstanceExportTask(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.CreateInstanceExportTask(params)
if err != nil {
return nil, errors.Wrap(err, "CreateInstanceExportTask")
}
@@ -471,7 +483,11 @@ func (self *SRegion) getImages(status ImageStatusType, owners []TImageOwnerType,
params.SetFilters(filters)
}
ret, err := self.ec2Client.DescribeImages(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeImages(params)
err = parseNotFoundError(err)
if err != nil {
return nil, errors.Wrap(err, "parseNotFoundError")
@@ -554,8 +570,12 @@ func (self *SRegion) getImages(status ImageStatusType, owners []TImageOwnerType,
func (self *SRegion) DeleteImage(imageId string) error {
params := &ec2.DeregisterImageInput{}
params.SetImageId(imageId)
_, err := self.ec2Client.DeregisterImage(params)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.DeregisterImage(params)
return errors.Wrap(err, "DeregisterImage")
}
func (self *SRegion) addTags(resId string, key string, value string) error {
@@ -565,9 +585,13 @@ func (self *SRegion) addTags(resId string, key string, value string) error {
tag.Key = &key
tag.Value = &value
input.SetTags([]*ec2.Tag{&tag})
_, err := self.ec2Client.CreateTags(input)
ec2Client, err := self.getEc2Client()
if err != nil {
return err
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.CreateTags(input)
if err != nil {
return errors.Wrap(err, "CreateTags")
}
return nil
}
+122 -32
View File
@@ -123,9 +123,13 @@ func (self *SInstance) UpdateUserData(userData string) error {
input := &ec2.ModifyInstanceAttributeInput{}
input.SetUserData(udata)
input.SetInstanceId(self.GetId())
_, err := self.host.zone.region.ec2Client.ModifyInstanceAttribute(input)
ec2Client, err := self.host.zone.region.getEc2Client()
if err != nil {
return err
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.ModifyInstanceAttribute(input)
if err != nil {
return errors.Wrap(err, "ModifyInstanceAttribute")
}
return nil
@@ -135,7 +139,11 @@ func (self *SInstance) GetUserData() (string, error) {
input := &ec2.DescribeInstanceAttributeInput{}
input.SetInstanceId(self.GetId())
input.SetAttribute("userData")
ret, err := self.host.zone.region.ec2Client.DescribeInstanceAttribute(input)
ec2Client, err := self.host.zone.region.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeInstanceAttribute(input)
if err != nil {
return "", err
}
@@ -208,7 +216,11 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
// 注意:除了空用大写NA.其他一律用小写格式
priceKey := fmt.Sprintf("%s::%s::%s::NA::NA::shared::boxusage", self.RegionId, self.InstanceType, strings.ToLower(self.OSType))
data.Add(jsonutils.NewString(priceKey), "price_key")
tags, err := FetchTags(self.host.zone.region.ec2Client, self.InstanceId)
ec2Client, err := self.host.zone.region.getEc2Client()
if err != nil {
return data
}
tags, err := FetchTags(ec2Client, self.InstanceId)
if err != nil {
log.Errorln(err)
} else {
@@ -250,8 +262,12 @@ func (self *SInstance) GetSysTags() map[string]string {
data["login_key"] = loginKey
}
}
ec2Client, err := self.host.zone.region.getEc2Client()
if err != nil {
return data
}
// Name tag
tags, err := FetchTags(self.host.zone.region.ec2Client, self.InstanceId)
tags, err := FetchTags(ec2Client, self.InstanceId)
if err == nil {
name, err := tags.GetString("Name")
if err == nil {
@@ -262,7 +278,11 @@ func (self *SInstance) GetSysTags() map[string]string {
}
func (self *SInstance) GetTags() (map[string]string, error) {
tags, err := FetchTags(self.host.zone.region.ec2Client, self.InstanceId)
ec2Client, err := self.host.zone.region.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
tags, err := FetchTags(ec2Client, self.InstanceId)
if err != nil {
return nil, errors.Wrap(err, "FetchTags(self.host.zone.region.ec2Client, self.InstanceId)")
}
@@ -441,7 +461,12 @@ func (self *SInstance) DeleteVM(ctx context.Context) error {
}
params := &ec2.DescribeInstancesInput{InstanceIds: []*string{&self.InstanceId}}
return self.host.zone.region.ec2Client.WaitUntilInstanceTerminated(params)
ec2Client, err := self.host.zone.region.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
return ec2Client.WaitUntilInstanceTerminated(params)
}
func (self *SInstance) UpdateVM(ctx context.Context, name string) error {
@@ -595,7 +620,11 @@ func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit
params = params.SetFilters(filters)
}
res, err := self.ec2Client.DescribeInstances(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, 0, errors.Wrap(err, "getEc2Client")
}
res, err := ec2Client.DescribeInstances(params)
if err != nil {
if strings.Contains(err.Error(), "InvalidInstanceID.NotFound") {
return nil, 0, errors.Wrap(cloudprovider.ErrNotFound, "DescribeInstances")
@@ -746,7 +775,12 @@ func (self *SRegion) GetInstanceIdByImageId(imageId string) (string, error) {
filters := []*ec2.Filter{}
filters = AppendSingleValueFilter(filters, "image-id", imageId)
params.SetFilters(filters)
ret, err := self.ec2Client.DescribeInstances(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeInstances(params)
if err != nil {
return "", err
}
@@ -881,7 +915,11 @@ func (self *SRegion) CreateInstance(name string, image *SImage, instanceType str
params.SetSecurityGroupIds([]*string{&securityGroupId})
}
res, err := self.ec2Client.RunInstances(&params)
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
res, err := ec2Client.RunInstances(&params)
if err != nil {
log.Errorf("CreateInstance fail %s", err)
return "", err
@@ -925,8 +963,12 @@ func (self *SRegion) StartVM(instanceId string) error {
params := &ec2.StartInstancesInput{}
params.SetInstanceIds([]*string{&instanceId})
_, err := self.ec2Client.StartInstances(params)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.StartInstances(params)
return errors.Wrap(err, "StartInstances")
}
func (self *SRegion) StopVM(instanceId string, isForce bool) error {
@@ -936,8 +978,12 @@ func (self *SRegion) StopVM(instanceId string, isForce bool) error {
params := &ec2.StopInstancesInput{}
params.SetInstanceIds([]*string{&instanceId})
_, err := self.ec2Client.StopInstances(params)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.StopInstances(params)
return errors.Wrap(err, "StopInstances")
}
func (self *SRegion) DeleteVM(instanceId string) error {
@@ -961,8 +1007,12 @@ func (self *SRegion) DeleteVM(instanceId string) error {
params := &ec2.TerminateInstancesInput{}
params.SetInstanceIds([]*string{&instanceId})
_, err = self.ec2Client.TerminateInstances(params)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.TerminateInstances(params)
return errors.Wrap(err, "TerminateInstances")
}
func (self *SRegion) DeployVM(instanceId string, name string, password string, keypairName string, deleteKeypair bool, description string) error {
@@ -990,10 +1040,15 @@ func (self *SRegion) DeployVM(instanceId string, name string, password string, k
tagspec.SetDescTag(description)
}
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
ec2Tag, _ := tagspec.GetTagSpecifications()
if len(ec2Tag.Tags) > 0 {
params.SetTags(ec2Tag.Tags)
_, err := self.ec2Client.CreateTags(params)
_, err := ec2Client.CreateTags(params)
if err != nil {
return err
}
@@ -1059,13 +1114,18 @@ func (self *SRegion) ReplaceSystemDisk(ctx context.Context, instanceId string, i
return "", fmt.Errorf("ReplaceSystemDisk create temp server failed.")
}
self.ec2Client.WaitUntilInstanceRunning(&ec2.DescribeInstancesInput{InstanceIds: []*string{&_id}})
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ec2Client.WaitUntilInstanceRunning(&ec2.DescribeInstancesInput{InstanceIds: []*string{&_id}})
err = self.StopVM(_id, true)
if err != nil {
log.Debugf("ReplaceSystemDisk stop temp server failed %s", err)
return "", fmt.Errorf("ReplaceSystemDisk stop temp server failed")
}
self.ec2Client.WaitUntilInstanceStopped(&ec2.DescribeInstancesInput{InstanceIds: []*string{&_id}})
ec2Client.WaitUntilInstanceStopped(&ec2.DescribeInstancesInput{InstanceIds: []*string{&_id}})
// detach disks
tempInstance, err := self.GetInstance(_id)
@@ -1085,16 +1145,16 @@ func (self *SRegion) ReplaceSystemDisk(ctx context.Context, instanceId string, i
log.Debugf("ReplaceSystemDisk detach disk %s: %s", tempInstance.Disks[0], err)
return "", err
}
self.ec2Client.WaitUntilVolumeAvailable(&ec2.DescribeVolumesInput{VolumeIds: []*string{&rootDisk.DiskId}})
self.ec2Client.WaitUntilVolumeAvailable(&ec2.DescribeVolumesInput{VolumeIds: []*string{&tempInstance.Disks[0]}})
ec2Client.WaitUntilVolumeAvailable(&ec2.DescribeVolumesInput{VolumeIds: []*string{&rootDisk.DiskId}})
ec2Client.WaitUntilVolumeAvailable(&ec2.DescribeVolumesInput{VolumeIds: []*string{&tempInstance.Disks[0]}})
err = self.AttachDisk(instance.GetId(), tempInstance.Disks[0], rootDisk.Device)
if err != nil {
log.Debugf("ReplaceSystemDisk attach disk %s: %s", tempInstance.Disks[0], err)
return "", err
}
self.ec2Client.WaitUntilInstanceStopped(&ec2.DescribeInstancesInput{InstanceIds: []*string{&instanceId}})
self.ec2Client.WaitUntilVolumeInUse(&ec2.DescribeVolumesInput{VolumeIds: []*string{&tempInstance.Disks[0]}})
ec2Client.WaitUntilInstanceStopped(&ec2.DescribeInstancesInput{InstanceIds: []*string{&instanceId}})
ec2Client.WaitUntilVolumeInUse(&ec2.DescribeVolumesInput{VolumeIds: []*string{&tempInstance.Disks[0]}})
userdataText, err := base64.StdEncoding.DecodeString(userdata)
if err != nil {
@@ -1120,7 +1180,11 @@ func (self *SRegion) ChangeVMConfig2(zoneId string, instanceId string, instanceT
t := &ec2.AttributeValue{Value: &instanceType}
params.SetInstanceType(t)
_, err := self.ec2Client.ModifyInstanceAttribute(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.ModifyInstanceAttribute(params)
if err != nil {
return fmt.Errorf("Failed to change vm config, specification not supported. %s", err.Error())
} else {
@@ -1133,7 +1197,13 @@ func (self *SRegion) DetachDisk(instanceId string, diskId string) error {
params.SetInstanceId(instanceId)
params.SetVolumeId(diskId)
log.Debugf("DetachDisk %s", params.String())
_, err := self.ec2Client.DetachVolume(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.DetachVolume(params)
if err != nil {
if strings.Contains(err.Error(), fmt.Sprintf("'%s'is in the 'available' state", diskId)) {
return nil
@@ -1153,15 +1223,23 @@ func (self *SRegion) AttachDisk(instanceId string, diskId string, deviceName str
params.SetVolumeId(diskId)
params.SetDevice(deviceName)
log.Debugf("AttachDisk %s", params.String())
_, err := self.ec2Client.AttachVolume(params)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.AttachVolume(params)
return errors.Wrap(err, "AttachVolume")
}
func (self *SRegion) deleteProtectStatusVM(instanceId string) (bool, error) {
p := &ec2.DescribeInstanceAttributeInput{}
p.SetInstanceId(instanceId)
p.SetAttribute("disableApiTermination")
ret, err := self.ec2Client.DescribeInstanceAttribute(p)
ec2Client, err := self.getEc2Client()
if err != nil {
return false, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeInstanceAttribute(p)
if err != nil {
return false, err
}
@@ -1174,15 +1252,23 @@ func (self *SRegion) deleteProtectVM(instanceId string, disableDelete bool) erro
DisableApiTermination: &ec2.AttributeBooleanValue{Value: &disableDelete},
InstanceId: &instanceId,
}
_, err := self.ec2Client.ModifyInstanceAttribute(p2)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.ModifyInstanceAttribute(p2)
return errors.Wrap(err, "ModifyInstanceAttribute")
}
func (self *SRegion) getPasswordData(instanceId string) (string, error) {
params := &ec2.GetPasswordDataInput{}
params.SetInstanceId(instanceId)
ret, err := self.ec2Client.GetPasswordData(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.GetPasswordData(params)
if err != nil {
return "", err
}
@@ -1207,7 +1293,11 @@ func (self *SInstance) GetError() error {
}
func (self *SInstance) SetTags(tags map[string]string, replace bool) error {
oldTagsJson, err := FetchTags(self.host.zone.region.ec2Client, self.InstanceId)
ec2Client, err := self.host.zone.region.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
oldTagsJson, err := FetchTags(ec2Client, self.InstanceId)
if err != nil {
return errors.Wrapf(err, "FetchTags(self.host.zone.region.ec2Client, %s)", self.InstanceId)
}
+5 -1
View File
@@ -73,7 +73,11 @@ func (self *SInstanceNic) GetINetwork() cloudprovider.ICloudNetwork {
}
func (self *SInstanceNic) getEc2Client() *ec2.EC2 {
return self.instance.host.zone.region.ec2Client
ec2Client, err := self.instance.host.zone.region.getEc2Client()
if err != nil {
return nil
}
return ec2Client
}
func (self *SInstanceNic) GetSubAddress() ([]string, error) {
+10 -2
View File
@@ -91,7 +91,11 @@ func (self *SRegion) GetKeypairs(finger string, name string, offset int, limit i
params.SetFilters(filters)
}
ret, err := self.ec2Client.DescribeKeyPairs(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, 0, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeKeyPairs(params)
if err != nil {
return nil, 0, err
}
@@ -113,7 +117,11 @@ func (self *SRegion) ImportKeypair(name string, pubKey string) (*SKeypair, error
params := &ec2.ImportKeyPairInput{}
params.SetKeyName(name)
params.SetPublicKeyMaterial([]byte(pubKey))
ret, err := self.ec2Client.ImportKeyPair(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.ImportKeyPair(params)
if err != nil {
return nil, errors.Wrap(err, "ImportKeyPair")
} else {
+1 -1
View File
@@ -23,7 +23,7 @@ import (
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
"us-east-2": {Latitude: 40.4172871, Longitude: -82.90712300000001, City: api.CITY_OHIO, CountryCode: api.COUNTRY_CODE_US},
"us-east-1": {Latitude: 37.4315734, Longitude: -78.6568942, City: api.CITY_N_VIRGINIA, CountryCode: api.COUNTRY_CODE_US},
"us-east-1": {Latitude: 37.4315734, Longitude: -78.6568942, City: api.CITY_VIRGINIA, CountryCode: api.COUNTRY_CODE_US},
"us-west-1": {Latitude: 38.8375215, Longitude: -120.8958242, City: api.CITY_N_CALIFORNIA, CountryCode: api.COUNTRY_CODE_US},
"us-west-2": {Latitude: 43.8041334, Longitude: -120.5542012, City: api.CITY_OREGON, CountryCode: api.COUNTRY_CODE_US},
"ap-south-1": {Latitude: 19.0759837, Longitude: 72.8776559, City: api.CITY_MUMBAI, CountryCode: api.COUNTRY_CODE_IN},
+18 -5
View File
@@ -187,7 +187,11 @@ func (self *SRegion) createNetwork(zoneId string, vpcId string, name string, cid
params.SetVpcId(vpcId)
params.SetCidrBlock(cidr)
ret, err := self.ec2Client.CreateSubnet(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.CreateSubnet(params)
if err != nil {
return "", err
} else {
@@ -198,7 +202,7 @@ func (self *SRegion) createNetwork(zoneId string, vpcId string, name string, cid
ec2Tag, _ := tagspec.GetTagSpecifications()
paramsTags.SetResources([]*string{ret.Subnet.SubnetId})
paramsTags.SetTags(ec2Tag.Tags)
_, err := self.ec2Client.CreateTags(paramsTags)
_, err := ec2Client.CreateTags(paramsTags)
if err != nil {
log.Infof("createNetwork write tags failed:%s", err)
}
@@ -224,8 +228,12 @@ func (self *SRegion) getNetwork(networkId string) (*SNetwork, error) {
func (self *SRegion) deleteNetwork(networkId string) error {
params := &ec2.DeleteSubnetInput{}
params.SetSubnetId(networkId)
_, err := self.ec2Client.DeleteSubnet(params)
return err
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.DeleteSubnet(params)
return errors.Wrap(err, "DeleteSubnet")
}
func (self *SRegion) GetNetwroks(ids []string, vpcId string, limit int, offset int) ([]SNetwork, int, error) {
@@ -247,7 +255,12 @@ func (self *SRegion) GetNetwroks(ids []string, vpcId string, limit int, offset i
params.SetFilters(filters)
}
ret, err := self.ec2Client.DescribeSubnets(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, 0, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeSubnets(params)
err = parseNotFoundError(err)
if err != nil {
return nil, 0, err
+131
View File
@@ -0,0 +1,131 @@
package aws
import (
"fmt"
"strings"
"time"
"github.com/aws/aws-sdk-go/service/organizations"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
/*
* {"arn":"arn:aws:organizations::285906155448:account/o-vgh74bqhdw/285906155448","email":"swordqiu@gmail.com","id":"285906155448","joined_method":"INVITED","joined_timestamp":"2021-02-09T03:55:27.724000Z","name":"qiu jian","status":"ACTIVE"}
*/
type SAccount struct {
ID string `json:"id"`
Name string `json:"name"`
Arn string `json:"arn"`
Email string `json:"email"`
Status string `json:"status"`
JoinedMethod string `json:"joined_method"`
JoinedTimestamp time.Time `json:"joined_timestamp"`
IsMaster bool `json:"is_master"`
}
func (r *SRegion) ListAccounts() ([]SAccount, error) {
orgCli, err := r.getOrganizationClient()
if err != nil {
return nil, errors.Wrap(err, "GetOrganizationClient")
}
input := organizations.DescribeOrganizationInput{}
orgOutput, err := orgCli.DescribeOrganization(&input)
if err != nil {
log.Errorf("%#v", err)
return nil, errors.Wrap(err, "DescribeOrganization")
}
var nextToken *string
accounts := make([]SAccount, 0)
for {
input := organizations.ListAccountsInput{}
if nextToken != nil {
input.NextToken = nextToken
}
parts, err := orgCli.ListAccounts(&input)
if err != nil {
return nil, errors.Wrap(err, "ListAccounts")
}
for _, actPtr := range parts.Accounts {
account := SAccount{
ID: *actPtr.Id,
Name: *actPtr.Name,
Arn: *actPtr.Arn,
Email: *actPtr.Email,
Status: *actPtr.Status,
JoinedMethod: *actPtr.JoinedMethod,
JoinedTimestamp: *actPtr.JoinedTimestamp,
}
if *orgOutput.Organization.MasterAccountId == *actPtr.Id {
account.IsMaster = true
}
accounts = append(accounts, account)
}
if parts.NextToken == nil || len(*parts.NextToken) == 0 {
break
} else {
nextToken = parts.NextToken
}
}
return accounts, nil
}
func (self *SAwsClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
// todo: implement me
err := self.fetchRegions()
if err != nil {
return nil, errors.Wrap(err, "fetchRegions")
}
accounts, err := self.getDefaultRegion().ListAccounts()
if err != nil {
// find errors
if strings.Contains(err.Error(), "AWSOrganizationsNotInUseException") || strings.Contains(err.Error(), "AccessDeniedException") {
// permission denied, fall back to single account mode
subAccount := cloudprovider.SSubAccount{}
subAccount.Name = self.cpcfg.Name
subAccount.Account = self.accessKey
subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
return []cloudprovider.SSubAccount{subAccount}, nil
} else {
return nil, errors.Wrap(err, "ListAccounts")
}
} else {
// check if caller is a root caller
caller, _ := self.GetCallerIdentity()
isRootAccount := false
// arn:aws:iam::285906155448:root
if caller != nil && strings.HasSuffix(caller.Arn, ":root") {
log.Debugf("root %s", caller.Arn)
isRootAccount = true
}
subAccounts := []cloudprovider.SSubAccount{}
for _, account := range accounts {
subAccount := cloudprovider.SSubAccount{}
if account.Status == "ACTIVE" {
subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
} else {
subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_SUSPENDED
}
if account.IsMaster {
subAccount.Name = self.cpcfg.Name
subAccount.Account = self.accessKey
} else {
if isRootAccount {
log.Warningf("Cannot access non-master account with root account!!")
subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NO_PERMISSION
}
subAccount.Name = fmt.Sprintf("%s/%s", account.Name, account.ID)
subAccount.Account = fmt.Sprintf("%s/%s", self.accessKey, account.ID)
}
subAccounts = append(subAccounts, subAccount)
}
return subAccounts, nil
}
}
+19 -3
View File
@@ -16,6 +16,7 @@ package provider
import (
"context"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
@@ -187,10 +188,23 @@ func (self *SAwsProviderFactory) ValidateUpdateCloudaccountCredential(ctx contex
return output, nil
}
func parseAccount(account, secret string) (accessKey string, secretKey string, accountId string) {
slash := strings.Index(account, "/")
if slash > 0 {
accessKey = account[:slash]
accountId = account[slash+1:]
} else {
accessKey = account
}
secretKey = secret
return
}
func (self *SAwsProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) (cloudprovider.ICloudProvider, error) {
accessKey, secret, accountId := parseAccount(cfg.Account, cfg.Secret)
client, err := aws.NewAwsClient(
aws.NewAwsClientConfig(
cfg.URL, cfg.Account, cfg.Secret,
cfg.URL, accessKey, secret, accountId,
).CloudproviderConfig(cfg),
)
if err != nil {
@@ -203,11 +217,13 @@ func (self *SAwsProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) (
}
func (self *SAwsProviderFactory) GetClientRC(info cloudprovider.SProviderInfo) (map[string]string, error) {
accessKey, secret, accountId := parseAccount(info.Account, info.Secret)
return map[string]string{
"AWS_ACCESS_URL": info.Url,
"AWS_ACCESS_KEY": info.Account,
"AWS_SECRET": info.Secret,
"AWS_ACCESS_KEY": accessKey,
"AWS_SECRET": secret,
"AWS_REGION": aws.GetDefaultRegionId(info.Url),
"AWS_ACCOUNT_ID": accountId,
}, nil
}
+38 -8
View File
@@ -36,6 +36,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/organizations"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
"github.com/aws/aws-sdk-go/service/s3"
@@ -133,6 +134,7 @@ type SRegion struct {
s3Client *s3.S3
elbv2Client *elbv2.ELBV2
acmClient *acm.ACM
organizationClient *organizations.Organizations
resourceGroupTagClient *resourcegroupstaggingapi.ResourceGroupsTaggingAPI
izones []cloudprovider.ICloudZone
@@ -163,7 +165,6 @@ func (self *SRegion) getEc2Client() (*ec2.EC2, error) {
}
self.ec2Client = ec2.New(s)
return self.ec2Client, nil
}
return self.ec2Client, nil
@@ -194,6 +195,17 @@ func (self *SRegion) GetS3Client() (*s3.S3, error) {
return self.s3Client, nil
}
func (r *SRegion) getOrganizationClient() (*organizations.Organizations, error) {
if r.organizationClient == nil {
s, err := r.getAwsSession()
if err != nil {
return nil, errors.Wrap(err, "getAwsSession")
}
r.organizationClient = organizations.New(s)
}
return r.organizationClient, nil
}
func (self *SRegion) getResourceGroupTagClient() (*resourcegroupstaggingapi.ResourceGroupsTaggingAPI, error) {
if self.resourceGroupTagClient == nil {
s, err := self.getAwsSession()
@@ -360,10 +372,14 @@ func (self *SRegion) GetElbV2Client() (*elbv2.ELBV2, error) {
/////////////////////////////////////////////////////////////////////////////
func (self *SRegion) fetchZones() error {
// todo: 这里将过滤出指定region下全部的zones。是否只过滤出可用的zone即可? The state of the Availability Zone (available | information | impaired | unavailable)
zones, err := self.ec2Client.DescribeAvailabilityZones(&ec2.DescribeAvailabilityZonesInput{})
ec2Client, err := self.getEc2Client()
if err != nil {
return err
return errors.Wrap(err, "getEc2Client")
}
// todo: 这里将过滤出指定region下全部的zones。是否只过滤出可用的zone即可? The state of the Availability Zone (available | information | impaired | unavailable)
zones, err := ec2Client.DescribeAvailabilityZones(&ec2.DescribeAvailabilityZonesInput{})
if err != nil {
return errors.Wrap(err, "DescribeAvailabilityZones")
}
err = FillZero(zones)
if err != nil {
@@ -379,7 +395,12 @@ func (self *SRegion) fetchZones() error {
}
func (self *SRegion) fetchIVpcs() error {
vpcs, err := self.ec2Client.DescribeVpcs(&ec2.DescribeVpcsInput{})
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
vpcs, err := ec2Client.DescribeVpcs(&ec2.DescribeVpcsInput{})
if err != nil {
return err
}
@@ -671,14 +692,19 @@ func (self *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudpro
return nil, errors.Wrap(err, "GetTagSpecifications")
}
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
// start create vpc
vpc, err := self.ec2Client.CreateVpc(&ec2.CreateVpcInput{CidrBlock: &cidr})
vpc, err := ec2Client.CreateVpc(&ec2.CreateVpcInput{CidrBlock: &cidr})
if err != nil {
return nil, errors.Wrap(err, "CreateVpc")
}
tagsParams := &ec2.CreateTagsInput{Resources: []*string{vpc.Vpc.VpcId}, Tags: spec.Tags}
_, err = self.ec2Client.CreateTags(tagsParams)
_, err = ec2Client.CreateTags(tagsParams)
if err != nil {
log.Debugf("CreateIVpc add tag failed %s", err.Error())
}
@@ -1150,8 +1176,12 @@ func (region *SRegion) GetCapabilities() []string {
}
func (region *SRegion) CreateInternetGateway() (cloudprovider.ICloudInternetGateway, error) {
ec2Client, err := region.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
input := ec2.CreateInternetGatewayInput{}
output, err := region.ec2Client.CreateInternetGateway(&input)
output, err := ec2Client.CreateInternetGateway(&input)
if err != nil {
return nil, errors.Wrap(err, "CreateInternetGateway")
}
+11 -2
View File
@@ -18,11 +18,16 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
)
func (self *SRegion) GetReservedInstance() error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
params := &ec2.DescribeReservedInstancesInput{}
res, err := self.ec2Client.DescribeReservedInstances(params)
res, err := ec2Client.DescribeReservedInstances(params)
if err != nil {
log.Errorf("DescribeReservedInstances fail %s", err)
return err
@@ -41,7 +46,11 @@ type SReservedHostOffering struct {
}
func (self *SRegion) GetReservedHostOfferings() error {
res, err := self.ec2Client.DescribeHostReservationOfferings(nil)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
res, err := ec2Client.DescribeHostReservationOfferings(nil)
if err != nil {
log.Errorf("DescribeHostReservationOfferings fail %s", err)
return err
+38 -8
View File
@@ -171,6 +171,11 @@ func (self *SRouteTable) GetIRoutes() ([]cloudprovider.ICloudRoute, error) {
}
func (self *SRegion) GetRouteTables(vpcId string, mainRouteOnly bool) ([]SRouteTable, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
input := &ec2.DescribeRouteTablesInput{}
filters := make([]*ec2.Filter, 0)
filters = AppendSingleValueFilter(filters, "vpc-id", vpcId)
@@ -180,7 +185,7 @@ func (self *SRegion) GetRouteTables(vpcId string, mainRouteOnly bool) ([]SRouteT
input.SetFilters(filters)
ret, err := self.ec2Client.DescribeRouteTables(input)
ret, err := ec2Client.DescribeRouteTables(input)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetRouteTables.DescribeRouteTables")
}
@@ -222,7 +227,11 @@ func (self *SRegion) CreateRoute(routeTableId string, DestinationCIDRBlock strin
default:
return fmt.Errorf("invalid aws vpc targetid:%s", targetId)
}
_, err := self.ec2Client.CreateRoute(input)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.CreateRoute(input)
if err != nil {
return errors.Wrapf(err, "self.ec2Client.CreateRoute(%s)", jsonutils.Marshal(input).String())
}
@@ -253,7 +262,11 @@ func (self *SRegion) ReplaceRoute(routeTableId string, DestinationCIDRBlock stri
default:
return fmt.Errorf("invalid aws vpc targetid:%s", targetId)
}
_, err := self.ec2Client.ReplaceRoute(input)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.ReplaceRoute(input)
if err != nil {
return errors.Wrapf(err, "self.ec2Client.ReplaceRouteInput(%s)", jsonutils.Marshal(input).String())
}
@@ -261,10 +274,14 @@ func (self *SRegion) ReplaceRoute(routeTableId string, DestinationCIDRBlock stri
}
func (self *SRegion) RemoveRoute(routeTableId string, DestinationCIDRBlock string) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
input := &ec2.DeleteRouteInput{}
input.RouteTableId = &routeTableId
input.DestinationCidrBlock = &DestinationCIDRBlock
_, err := self.ec2Client.DeleteRoute(input)
_, err = ec2Client.DeleteRoute(input)
if err != nil {
return errors.Wrapf(err, "self.ec2Client.DeleteRoute(%s)", jsonutils.Marshal(input).String())
}
@@ -272,13 +289,18 @@ func (self *SRegion) RemoveRoute(routeTableId string, DestinationCIDRBlock strin
}
func (self *SRegion) GetRouteTablesByNetworkId(netId string) ([]SRouteTable, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
input := &ec2.DescribeRouteTablesInput{}
filter := &ec2.Filter{}
filter.SetName("association.subnet-id")
filter.SetValues([]*string{&netId})
input.SetFilters([]*ec2.Filter{filter})
ret, err := self.ec2Client.DescribeRouteTables(input)
ret, err := ec2Client.DescribeRouteTables(input)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetRouteTables.DescribeRouteTables")
}
@@ -297,10 +319,14 @@ func (self *SRegion) GetRouteTablesByNetworkId(netId string) ([]SRouteTable, err
}
func (self *SRegion) GetRouteTable(id string) (*SRouteTable, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
input := &ec2.DescribeRouteTablesInput{}
input.RouteTableIds = []*string{&id}
ret, err := self.ec2Client.DescribeRouteTables(input)
ret, err := ec2Client.DescribeRouteTables(input)
if err != nil {
return nil, errors.Wrap(err, "SRegion.GetRouteTables.DescribeRouteTables")
}
@@ -325,7 +351,11 @@ func (self *SRegion) DeleteRouteTable(rid string) error {
input := &ec2.DeleteRouteTableInput{}
input.SetRouteTableId(rid)
_, err := self.ec2Client.DeleteRouteTable(input)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.DeleteRouteTable(input)
if err != nil {
return errors.Wrap(err, "DeleteRouteTable")
}
+44 -12
View File
@@ -151,6 +151,11 @@ func (self *SRegion) addSecurityGroupRules(secGrpId string, rule cloudprovider.S
}
func (self *SRegion) addSecurityGroupRule(secGrpId string, rule cloudprovider.SecurityRule) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
ipPermissions, err := YunionSecRuleToAws(rule)
log.Debugf("Aws security group rule: %s", ipPermissions)
if err != nil {
@@ -161,14 +166,14 @@ func (self *SRegion) addSecurityGroupRule(secGrpId string, rule cloudprovider.Se
params := &ec2.AuthorizeSecurityGroupIngressInput{}
params.SetGroupId(secGrpId)
params.SetIpPermissions(ipPermissions)
_, err = self.ec2Client.AuthorizeSecurityGroupIngress(params)
_, err = ec2Client.AuthorizeSecurityGroupIngress(params)
}
if rule.Direction == secrules.SecurityRuleEgress {
params := &ec2.AuthorizeSecurityGroupEgressInput{}
params.SetGroupId(secGrpId)
params.SetIpPermissions(ipPermissions)
_, err = self.ec2Client.AuthorizeSecurityGroupEgress(params)
_, err = ec2Client.AuthorizeSecurityGroupEgress(params)
}
if err != nil && strings.Contains(err.Error(), "InvalidPermission.Duplicate") {
@@ -180,6 +185,11 @@ func (self *SRegion) addSecurityGroupRule(secGrpId string, rule cloudprovider.Se
}
func (self *SRegion) DelSecurityGroupRule(secGrpId string, rule cloudprovider.SecurityRule) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
ipPermissions, err := YunionSecRuleToAws(rule)
if err != nil {
return err
@@ -189,14 +199,14 @@ func (self *SRegion) DelSecurityGroupRule(secGrpId string, rule cloudprovider.Se
params := &ec2.RevokeSecurityGroupIngressInput{}
params.SetGroupId(secGrpId)
params.SetIpPermissions(ipPermissions)
_, err = self.ec2Client.RevokeSecurityGroupIngress(params)
_, err = ec2Client.RevokeSecurityGroupIngress(params)
}
if rule.Direction == secrules.SecurityRuleEgress {
params := &ec2.RevokeSecurityGroupEgressInput{}
params.SetGroupId(secGrpId)
params.SetIpPermissions(ipPermissions)
_, err = self.ec2Client.RevokeSecurityGroupEgress(params)
_, err = ec2Client.RevokeSecurityGroupEgress(params)
}
if err != nil {
@@ -212,11 +222,16 @@ func (self *SRegion) updateSecurityGroupRuleDescription(secGrpId string, rule cl
return err
}
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
if rule.Direction == secrules.SecurityRuleIngress {
params := &ec2.UpdateSecurityGroupRuleDescriptionsIngressInput{}
params.SetGroupId(secGrpId)
params.SetIpPermissions(ipPermissions)
ret, err := self.ec2Client.UpdateSecurityGroupRuleDescriptionsIngress(params)
ret, err := ec2Client.UpdateSecurityGroupRuleDescriptionsIngress(params)
if err != nil {
return err
} else if ret.Return != nil && *ret.Return == false {
@@ -228,7 +243,7 @@ func (self *SRegion) updateSecurityGroupRuleDescription(secGrpId string, rule cl
params := &ec2.UpdateSecurityGroupRuleDescriptionsEgressInput{}
params.SetGroupId(secGrpId)
params.SetIpPermissions(ipPermissions)
ret, err := self.ec2Client.UpdateSecurityGroupRuleDescriptionsEgress(params)
ret, err := ec2Client.UpdateSecurityGroupRuleDescriptionsEgress(params)
if err != nil {
return err
} else if ret.Return != nil && *ret.Return == false {
@@ -239,6 +254,11 @@ func (self *SRegion) updateSecurityGroupRuleDescription(secGrpId string, rule cl
}
func (self *SRegion) CreateSecurityGroup(vpcId string, name string, secgroupIdTag string, desc string) (string, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
params := &ec2.CreateSecurityGroupInput{}
params.SetVpcId(vpcId)
// 这里的描述aws 上层代码拼接的描述。并非用户提交的描述,用户描述放置在Yunion本地数据库中。)
@@ -251,7 +271,7 @@ func (self *SRegion) CreateSecurityGroup(vpcId string, name string, secgroupIdTa
}
params.SetGroupName(name)
group, err := self.ec2Client.CreateSecurityGroup(params)
group, err := ec2Client.CreateSecurityGroup(params)
if err != nil {
return "", err
}
@@ -266,7 +286,7 @@ func (self *SRegion) CreateSecurityGroup(vpcId string, name string, secgroupIdTa
tagParams := &ec2.CreateTagsInput{}
tagParams.SetResources([]*string{group.GroupId})
tagParams.SetTags(tags.Tags)
_, err = self.ec2Client.CreateTags(tagParams)
_, err = ec2Client.CreateTags(tagParams)
if err != nil {
return "", err
}
@@ -306,7 +326,11 @@ func (self *SRegion) GetSecurityGroupDetails(secGroupId string) (*SSecurityGroup
params := &ec2.DescribeSecurityGroupsInput{}
params.SetGroupIds([]*string{&secGroupId})
ret, err := self.ec2Client.DescribeSecurityGroups(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeSecurityGroups(params)
err = parseNotFoundError(err)
if err != nil {
return nil, errors.Wrap(err, "DescribeSecurityGroups")
@@ -366,9 +390,13 @@ func (self *SRegion) modifySecurityGroup(secGrpId string, name string, desc stri
params.SetTags(ec2Tags.Tags)
params.SetResources([]*string{&secGrpId})
_, err := self.ec2Client.CreateTags(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return err
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.CreateTags(params)
if err != nil {
return errors.Wrap(err, "CreateTags")
}
return nil
@@ -420,7 +448,11 @@ func (self *SRegion) GetSecurityGroups(vpcId string, name string, secgroupId str
params.SetFilters(filters)
}
ret, err := self.ec2Client.DescribeSecurityGroups(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, 0, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeSecurityGroups(params)
err = parseNotFoundError(err)
if err != nil {
return nil, 0, err
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2019 Yunion
//
// 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.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/aws"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type AccountListOptions struct {
}
shellutils.R(&AccountListOptions{}, "account-list", "List accounts", func(cli *aws.SRegion, args *AccountListOptions) error {
accounts, err := cli.ListAccounts()
if err != nil {
return err
}
printList(accounts, 0, 0, 0, []string{})
return nil
})
}
+21 -5
View File
@@ -136,7 +136,11 @@ func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName
params.SetSnapshotIds(ConvertedList(snapshotIds))
}
ret, err := self.ec2Client.DescribeSnapshots(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, 0, errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.DescribeSnapshots(params)
err = parseNotFoundError(err)
if err != nil {
if strings.Contains(err.Error(), "InvalidSnapshot.NotFound") {
@@ -200,15 +204,27 @@ func (self *SRegion) CreateSnapshot(diskId, name, desc string) (string, error) {
params.SetDescription(desc)
log.Debugf("CreateSnapshots with params %s", params)
ret, err := self.ec2Client.CreateSnapshot(params)
return StrVal(ret.SnapshotId), err
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.CreateSnapshot(params)
if err != nil {
return "", errors.Wrap(err, "CreateSnapshot")
}
return StrVal(ret.SnapshotId), nil
}
func (self *SRegion) DeleteSnapshot(snapshotId string) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
params := &ec2.DeleteSnapshotInput{}
params.SetSnapshotId(snapshotId)
_, err := self.ec2Client.DeleteSnapshot(params)
return err
_, err = ec2Client.DeleteSnapshot(params)
return errors.Wrap(err, "DeleteSnapshot")
}
func (self *SSnapshot) GetProjectId() string {
+11 -2
View File
@@ -252,6 +252,11 @@ func (self *SStoragecache) downloadImage(userCred mcclient.TokenCredential, imag
return nil, errors.Wrap(err, "GetInstanceIdByImageId")
}
ec2Client, err := self.region.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
task, err := self.region.ExportImage(instanceId, imageId)
if err != nil {
log.Errorf("ExportImage %s %s: %s", instanceId, imageId, err)
@@ -260,7 +265,7 @@ func (self *SStoragecache) downloadImage(userCred mcclient.TokenCredential, imag
taskParams := &ec2.DescribeExportTasksInput{}
taskParams.SetExportTaskIds([]*string{&task.TaskId})
if err := self.region.ec2Client.WaitUntilExportTaskCompleted(taskParams); err != nil {
if err := ec2Client.WaitUntilExportTaskCompleted(taskParams); err != nil {
log.Errorf("WaitUntilExportTaskCompleted %#v %s", taskParams, err)
return nil, errors.Wrap(err, "WaitUntilExportTaskCompleted")
}
@@ -476,7 +481,11 @@ func (self *SRegion) createIImage(snapshotId, imageName, imageDesc string) (stri
blockList := []*ec2.BlockDeviceMapping{block}
params.SetBlockDeviceMappings(blockList)
ret, err := self.ec2Client.CreateImage(params)
ec2Client, err := self.getEc2Client()
if err != nil {
return "", errors.Wrap(err, "getEc2Client")
}
ret, err := ec2Client.CreateImage(params)
if err != nil {
return "", err
}
+51 -11
View File
@@ -434,11 +434,16 @@ func (self *SVpc) GetExternalAccessMode() string {
}
func (self *SVpc) AttachInternetGateway(igwId string) error {
ec2Client, err := self.region.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
input := ec2.AttachInternetGatewayInput{}
input.SetInternetGatewayId(igwId)
input.SetVpcId(self.GetId())
_, err := self.region.ec2Client.AttachInternetGateway(&input)
_, err = ec2Client.AttachInternetGateway(&input)
if err != nil {
return errors.Wrap(err, "AttachInternetGateway")
}
@@ -500,11 +505,16 @@ func (self *SVpc) DetachInternetGateways() error {
}
func (self *SVpc) DetachInternetGateway(igwId string) error {
ec2Client, err := self.region.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
input := ec2.DetachInternetGatewayInput{}
input.SetInternetGatewayId(igwId)
input.SetVpcId(self.GetId())
_, err := self.region.ec2Client.DetachInternetGateway(&input)
_, err = ec2Client.DetachInternetGateway(&input)
if err != nil {
return errors.Wrap(err, "DetachInternetGateway")
}
@@ -513,10 +523,15 @@ func (self *SVpc) DetachInternetGateway(igwId string) error {
}
func (self *SVpc) DeleteInternetGateway(igwId string) error {
ec2Client, err := self.region.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
input := ec2.DeleteInternetGatewayInput{}
input.SetInternetGatewayId(igwId)
_, err := self.region.ec2Client.DeleteInternetGateway(&input)
_, err = ec2Client.DeleteInternetGateway(&input)
if err != nil {
return errors.Wrap(err, "DeleteInternetGateway")
}
@@ -576,7 +591,12 @@ func (self *SRegion) assignSecurityGroup(secgroupId, instanceId string) error {
func (self *SRegion) assignSecurityGroups(secgroupIds []*string, instanceId string) error {
instance, err := self.GetInstance(instanceId)
if err != nil {
return err
return errors.Wrap(err, "GetInstance")
}
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
for _, eth := range instance.NetworkInterfaces.NetworkInterface {
@@ -584,7 +604,7 @@ func (self *SRegion) assignSecurityGroups(secgroupIds []*string, instanceId stri
params.SetNetworkInterfaceId(eth.NetworkInterfaceId)
params.SetGroups(secgroupIds)
_, err := self.ec2Client.ModifyNetworkInterfaceAttribute(params)
_, err := ec2Client.ModifyNetworkInterfaceAttribute(params)
if err != nil {
return err
}
@@ -594,28 +614,43 @@ func (self *SRegion) assignSecurityGroups(secgroupIds []*string, instanceId stri
}
func (self *SRegion) DeleteSecurityGroup(secGrpId string) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
params := &ec2.DeleteSecurityGroupInput{}
params.SetGroupId(secGrpId)
_, err := self.ec2Client.DeleteSecurityGroup(params)
return err
_, err = ec2Client.DeleteSecurityGroup(params)
return errors.Wrap(err, "DeleteSecurityGroup")
}
func (self *SRegion) DeleteVpc(vpcId string) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
params := &ec2.DeleteVpcInput{}
params.SetVpcId(vpcId)
_, err := self.ec2Client.DeleteVpc(params)
return err
_, err = ec2Client.DeleteVpc(params)
return errors.Wrap(err, "DeleteVpc")
}
func (self *SRegion) GetVpcs(vpcId []string, offset int, limit int) ([]SVpc, int, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, 0, errors.Wrap(err, "getEc2Client")
}
params := &ec2.DescribeVpcsInput{}
if len(vpcId) > 0 {
params.SetVpcIds(ConvertedList(vpcId))
}
ret, err := self.ec2Client.DescribeVpcs(params)
ret, err := ec2Client.DescribeVpcs(params)
err = parseNotFoundError(err)
if err != nil {
return nil, 0, err
@@ -657,6 +692,11 @@ func (self *SRegion) GetVpcs(vpcId []string, offset int, limit int) ([]SVpc, int
}
func (self *SRegion) GetInternetGateways(vpcId string) ([]SInternetGateway, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
input := ec2.DescribeInternetGatewaysInput{}
filters := make([]*ec2.Filter, 0)
if len(vpcId) > 0 {
@@ -666,7 +706,7 @@ func (self *SRegion) GetInternetGateways(vpcId string) ([]SInternetGateway, erro
if len(filters) > 0 {
input.SetFilters(filters)
}
output, err := self.ec2Client.DescribeInternetGateways(&input)
output, err := ec2Client.DescribeInternetGateways(&input)
if err != nil {
return nil, errors.Wrap(err, "DescribeInternetGateways")
}
+43 -8
View File
@@ -41,6 +41,11 @@ func (self *SRegion) DescribeVpcPeeringConnections(vpcId string) ([]*ec2.VpcPeer
}
func (self *SRegion) DescribeRequesterVpcPeeringConnections(vpcId string) ([]*ec2.VpcPeeringConnection, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
params := ec2.DescribeVpcPeeringConnectionsInput{}
result := []*ec2.VpcPeeringConnection{}
var maxResult int64 = 20
@@ -53,7 +58,7 @@ func (self *SRegion) DescribeRequesterVpcPeeringConnections(vpcId string) ([]*ec
filter.Name = &filterName
params.Filters = []*ec2.Filter{&filter}
for {
ret, err := self.ec2Client.DescribeVpcPeeringConnections(&params)
ret, err := ec2Client.DescribeVpcPeeringConnections(&params)
if err != nil {
return nil, errors.Wrapf(err, "self.ec2Client.DescribeVpcPeeringConnections(%s)", jsonutils.Marshal(params).String())
}
@@ -67,6 +72,11 @@ func (self *SRegion) DescribeRequesterVpcPeeringConnections(vpcId string) ([]*ec
}
func (self *SRegion) DescribeAccepterVpcPeeringConnections(vpcId string) ([]*ec2.VpcPeeringConnection, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
params := ec2.DescribeVpcPeeringConnectionsInput{}
result := []*ec2.VpcPeeringConnection{}
var maxResult int64 = 20
@@ -78,7 +88,7 @@ func (self *SRegion) DescribeAccepterVpcPeeringConnections(vpcId string) ([]*ec2
filter.Name = &filterName
params.Filters = []*ec2.Filter{&filter}
for {
ret, err := self.ec2Client.DescribeVpcPeeringConnections(&params)
ret, err := ec2Client.DescribeVpcPeeringConnections(&params)
if err != nil {
return nil, errors.Wrapf(err, "self.ec2Client.DescribeVpcPeeringConnections(%s)", jsonutils.Marshal(params).String())
}
@@ -92,6 +102,11 @@ func (self *SRegion) DescribeAccepterVpcPeeringConnections(vpcId string) ([]*ec2
}
func (self *SRegion) GetVpcPeeringConnectionById(Id string) (*ec2.VpcPeeringConnection, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
params := ec2.DescribeVpcPeeringConnectionsInput{}
result := []*ec2.VpcPeeringConnection{}
var maxResult int64 = 20
@@ -102,7 +117,7 @@ func (self *SRegion) GetVpcPeeringConnectionById(Id string) (*ec2.VpcPeeringConn
filter.Name = &filterName
params.Filters = []*ec2.Filter{&filter}
for {
ret, err := self.ec2Client.DescribeVpcPeeringConnections(&params)
ret, err := ec2Client.DescribeVpcPeeringConnections(&params)
if err != nil {
return nil, errors.Wrapf(err, "self.ec2Client.DescribeVpcPeeringConnections(%s)", jsonutils.Marshal(params).String())
}
@@ -122,12 +137,17 @@ func (self *SRegion) GetVpcPeeringConnectionById(Id string) (*ec2.VpcPeeringConn
}
func (self *SRegion) CreateVpcPeeringConnection(vpcId string, opts *cloudprovider.VpcPeeringConnectionCreateOptions) (*ec2.VpcPeeringConnection, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
params := ec2.CreateVpcPeeringConnectionInput{}
params.VpcId = &vpcId
params.PeerVpcId = &opts.PeerVpcId
params.PeerRegion = &opts.PeerRegionId
params.PeerOwnerId = &opts.PeerAccountId
ret, err := self.ec2Client.CreateVpcPeeringConnection(&params)
ret, err := ec2Client.CreateVpcPeeringConnection(&params)
if err != nil {
return nil, errors.Wrapf(err, "self.ec2Client.CreateVpcPeeringConnection(%s)", jsonutils.Marshal(params).String())
}
@@ -137,7 +157,7 @@ func (self *SRegion) CreateVpcPeeringConnection(vpcId string, opts *cloudprovide
nametag := "Name"
desctag := "Description"
tagParams.Tags = []*ec2.Tag{{Key: &nametag, Value: &opts.Name}, {Key: &desctag, Value: &opts.Desc}}
_, err = self.ec2Client.CreateTags(&tagParams)
_, err = ec2Client.CreateTags(&tagParams)
if err != nil {
return nil, errors.Wrapf(err, "self.ec2Client.CreateTags(%s)", jsonutils.Marshal(tagParams).String())
}
@@ -146,9 +166,14 @@ func (self *SRegion) CreateVpcPeeringConnection(vpcId string, opts *cloudprovide
}
func (self *SRegion) DeleteVpcPeeringConnection(vpcPeeringConnectionId string) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
params := ec2.DeleteVpcPeeringConnectionInput{}
params.VpcPeeringConnectionId = &vpcPeeringConnectionId
_, err := self.ec2Client.DeleteVpcPeeringConnection(&params)
_, err = ec2Client.DeleteVpcPeeringConnection(&params)
if err != nil {
return errors.Wrapf(err, "self.ec2Client.DeleteVpcPeeringConnection(%s)", jsonutils.Marshal(params).String())
}
@@ -156,9 +181,14 @@ func (self *SRegion) DeleteVpcPeeringConnection(vpcPeeringConnectionId string) e
}
func (self *SRegion) AcceptVpcPeeringConnection(vpcPeeringConnectionId string) (*ec2.VpcPeeringConnection, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
params := ec2.AcceptVpcPeeringConnectionInput{}
params.VpcPeeringConnectionId = &vpcPeeringConnectionId
ret, err := self.ec2Client.AcceptVpcPeeringConnection(&params)
ret, err := ec2Client.AcceptVpcPeeringConnection(&params)
if err != nil {
return nil, errors.Wrapf(err, "self.ec2Client.AcceptVpcPeeringConnection(%s)", jsonutils.Marshal(params).String())
}
@@ -166,6 +196,11 @@ func (self *SRegion) AcceptVpcPeeringConnection(vpcPeeringConnectionId string) (
}
func (self *SRegion) DeleteVpcPeeringConnectionRoute(vpcPeeringConnectionId string) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
input := &ec2.DescribeRouteTablesInput{}
filters := make([]*ec2.Filter, 0)
filters = AppendSingleValueFilter(filters, "association.main", "true")
@@ -173,7 +208,7 @@ func (self *SRegion) DeleteVpcPeeringConnectionRoute(vpcPeeringConnectionId stri
input.SetFilters(filters)
routeTables := []*ec2.RouteTable{}
for {
ret, err := self.ec2Client.DescribeRouteTables(input)
ret, err := ec2Client.DescribeRouteTables(input)
if err != nil {
return errors.Wrap(err, "SRegion.GetRouteTables.DescribeRouteTables")
}
File diff suppressed because it is too large Load Diff
+28
View File
@@ -0,0 +1,28 @@
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
// Package organizations provides the client and types for making API
// requests to AWS Organizations.
//
// AWS Organizations
//
// See https://docs.aws.amazon.com/goto/WebAPI/organizations-2016-11-28 for more information on this service.
//
// See organizations package documentation for more information.
// https://docs.aws.amazon.com/sdk-for-go/api/service/organizations/
//
// Using the Client
//
// To contact AWS Organizations with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//
// See the SDK's documentation for more information on how to use the SDK.
// https://docs.aws.amazon.com/sdk-for-go/api/
//
// See aws.Config documentation for more information on configuring SDK clients.
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
//
// See the AWS Organizations client Organizations for more
// information on creating client for this service.
// https://docs.aws.amazon.com/sdk-for-go/api/service/organizations/#New
package organizations
+621
View File
@@ -0,0 +1,621 @@
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package organizations
import (
"github.com/aws/aws-sdk-go/private/protocol"
)
const (
// ErrCodeAWSOrganizationsNotInUseException for service response error code
// "AWSOrganizationsNotInUseException".
//
// Your account isn't a member of an organization. To make this request, you
// must use the credentials of an account that belongs to an organization.
ErrCodeAWSOrganizationsNotInUseException = "AWSOrganizationsNotInUseException"
// ErrCodeAccessDeniedException for service response error code
// "AccessDeniedException".
//
// You don't have permissions to perform the requested operation. The user or
// role that is making the request must have at least one IAM permissions policy
// attached that grants the required permissions. For more information, see
// Access Management (https://docs.aws.amazon.com/IAM/latest/UserGuide/access.html)
// in the IAM User Guide.
ErrCodeAccessDeniedException = "AccessDeniedException"
// ErrCodeAccessDeniedForDependencyException for service response error code
// "AccessDeniedForDependencyException".
//
// The operation that you attempted requires you to have the iam:CreateServiceLinkedRole
// for organizations.amazonaws.com permission so that AWS Organizations can
// create the required service-linked role. You don't have that permission.
ErrCodeAccessDeniedForDependencyException = "AccessDeniedForDependencyException"
// ErrCodeAccountAlreadyRegisteredException for service response error code
// "AccountAlreadyRegisteredException".
//
// The specified account is already a delegated administrator for this AWS service.
ErrCodeAccountAlreadyRegisteredException = "AccountAlreadyRegisteredException"
// ErrCodeAccountNotFoundException for service response error code
// "AccountNotFoundException".
//
// We can't find an AWS account with the AccountId that you specified, or the
// account whose credentials you used to make this request isn't a member of
// an organization.
ErrCodeAccountNotFoundException = "AccountNotFoundException"
// ErrCodeAccountNotRegisteredException for service response error code
// "AccountNotRegisteredException".
//
// The specified account is not a delegated administrator for this AWS service.
ErrCodeAccountNotRegisteredException = "AccountNotRegisteredException"
// ErrCodeAccountOwnerNotVerifiedException for service response error code
// "AccountOwnerNotVerifiedException".
//
// You can't invite an existing account to your organization until you verify
// that you own the email address associated with the management account. For
// more information, see Email Address Verification (http://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_create.html#about-email-verification)
// in the AWS Organizations User Guide.
ErrCodeAccountOwnerNotVerifiedException = "AccountOwnerNotVerifiedException"
// ErrCodeAlreadyInOrganizationException for service response error code
// "AlreadyInOrganizationException".
//
// This account is already a member of an organization. An account can belong
// to only one organization at a time.
ErrCodeAlreadyInOrganizationException = "AlreadyInOrganizationException"
// ErrCodeChildNotFoundException for service response error code
// "ChildNotFoundException".
//
// We can't find an organizational unit (OU) or AWS account with the ChildId
// that you specified.
ErrCodeChildNotFoundException = "ChildNotFoundException"
// ErrCodeConcurrentModificationException for service response error code
// "ConcurrentModificationException".
//
// The target of the operation is currently being modified by a different request.
// Try again later.
ErrCodeConcurrentModificationException = "ConcurrentModificationException"
// ErrCodeConstraintViolationException for service response error code
// "ConstraintViolationException".
//
// Performing this operation violates a minimum or maximum value limit. For
// example, attempting to remove the last service control policy (SCP) from
// an OU or root, inviting or creating too many accounts to the organization,
// or attaching too many policies to an account, OU, or root. This exception
// includes a reason that contains additional information about the violated
// limit:
//
// Some of the reasons in the following list might not be applicable to this
// specific API or operation.
//
// * ACCOUNT_CANNOT_LEAVE_ORGANIZAION: You attempted to remove the management
// account from the organization. You can't remove the management account.
// Instead, after you remove all member accounts, delete the organization
// itself.
//
// * ACCOUNT_CANNOT_LEAVE_WITHOUT_EULA: You attempted to remove an account
// from the organization that doesn't yet have enough information to exist
// as a standalone account. This account requires you to first agree to the
// AWS Customer Agreement. Follow the steps at Removing a member account
// from your organization (http://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_remove.html#orgs_manage_accounts_remove-from-master)in
// the AWS Organizations User Guide.
//
// * ACCOUNT_CANNOT_LEAVE_WITHOUT_PHONE_VERIFICATION: You attempted to remove
// an account from the organization that doesn't yet have enough information
// to exist as a standalone account. This account requires you to first complete
// phone verification. Follow the steps at Removing a member account from
// your organization (http://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_remove.html#orgs_manage_accounts_remove-from-master)
// in the AWS Organizations User Guide.
//
// * ACCOUNT_CREATION_RATE_LIMIT_EXCEEDED: You attempted to exceed the number
// of accounts that you can create in one day.
//
// * ACCOUNT_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the limit on
// the number of accounts in an organization. If you need more accounts,
// contact AWS Support (https://console.aws.amazon.com/support/home#/) to
// request an increase in your limit. Or the number of invitations that you
// tried to send would cause you to exceed the limit of accounts in your
// organization. Send fewer invitations or contact AWS Support to request
// an increase in the number of accounts. Deleted and closed accounts still
// count toward your limit. If you get this exception when running a command
// immediately after creating the organization, wait one hour and try again.
// After an hour, if the command continues to fail with this error, contact
// AWS Support (https://console.aws.amazon.com/support/home#/).
//
// * CANNOT_REGISTER_MASTER_AS_DELEGATED_ADMINISTRATOR: You attempted to
// register the management account of the organization as a delegated administrator
// for an AWS service integrated with Organizations. You can designate only
// a member account as a delegated administrator.
//
// * CANNOT_REMOVE_DELEGATED_ADMINISTRATOR_FROM_ORG: You attempted to remove
// an account that is registered as a delegated administrator for a service
// integrated with your organization. To complete this operation, you must
// first deregister this account as a delegated administrator.
//
// * CREATE_ORGANIZATION_IN_BILLING_MODE_UNSUPPORTED_REGION: To create an
// organization in the specified region, you must enable all features mode.
//
// * DELEGATED_ADMINISTRATOR_EXISTS_FOR_THIS_SERVICE: You attempted to register
// an AWS account as a delegated administrator for an AWS service that already
// has a delegated administrator. To complete this operation, you must first
// deregister any existing delegated administrators for this service.
//
// * EMAIL_VERIFICATION_CODE_EXPIRED: The email verification code is only
// valid for a limited period of time. You must resubmit the request and
// generate a new verfication code.
//
// * HANDSHAKE_RATE_LIMIT_EXCEEDED: You attempted to exceed the number of
// handshakes that you can send in one day.
//
// * MASTER_ACCOUNT_ADDRESS_DOES_NOT_MATCH_MARKETPLACE: To create an account
// in this organization, you first must migrate the organization's management
// account to the marketplace that corresponds to the management account's
// address. For example, accounts with India addresses must be associated
// with the AISPL marketplace. All accounts in an organization must be associated
// with the same marketplace.
//
// * MASTER_ACCOUNT_MISSING_BUSINESS_LICENSE: Applies only to the AWS Regions
// in China. To create an organization, the master must have an valid business
// license. For more information, contact customer support.
//
// * MASTER_ACCOUNT_MISSING_CONTACT_INFO: To complete this operation, you
// must first provide a valid contact address and phone number for the management
// account. Then try the operation again.
//
// * MASTER_ACCOUNT_NOT_GOVCLOUD_ENABLED: To complete this operation, the
// management account must have an associated account in the AWS GovCloud
// (US-West) Region. For more information, see AWS Organizations (http://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-organizations.html)
// in the AWS GovCloud User Guide.
//
// * MASTER_ACCOUNT_PAYMENT_INSTRUMENT_REQUIRED: To create an organization
// with this management account, you first must associate a valid payment
// instrument, such as a credit card, with the account. Follow the steps
// at To leave an organization when all required account information has
// not yet been provided (http://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_remove.html#leave-without-all-info)
// in the AWS Organizations User Guide.
//
// * MAX_DELEGATED_ADMINISTRATORS_FOR_SERVICE_LIMIT_EXCEEDED: You attempted
// to register more delegated administrators than allowed for the service
// principal.
//
// * MAX_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED: You attempted to exceed the
// number of policies of a certain type that can be attached to an entity
// at one time.
//
// * MAX_TAG_LIMIT_EXCEEDED: You have exceeded the number of tags allowed
// on this resource.
//
// * MEMBER_ACCOUNT_PAYMENT_INSTRUMENT_REQUIRED: To complete this operation
// with this member account, you first must associate a valid payment instrument,
// such as a credit card, with the account. Follow the steps at To leave
// an organization when all required account information has not yet been
// provided (http://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_remove.html#leave-without-all-info)
// in the AWS Organizations User Guide.
//
// * MIN_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED: You attempted to detach a
// policy from an entity that would cause the entity to have fewer than the
// minimum number of policies of a certain type required.
//
// * ORGANIZATION_NOT_IN_ALL_FEATURES_MODE: You attempted to perform an operation
// that requires the organization to be configured to support all features.
// An organization that supports only consolidated billing features can't
// perform this operation.
//
// * OU_DEPTH_LIMIT_EXCEEDED: You attempted to create an OU tree that is
// too many levels deep.
//
// * OU_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the number of OUs
// that you can have in an organization.
//
// * POLICY_CONTENT_LIMIT_EXCEEDED: You attempted to create a policy that
// is larger than the maximum size.
//
// * POLICY_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the number of
// policies that you can have in an organization.
//
// * TAG_POLICY_VIOLATION: You attempted to create or update a resource with
// tags that are not compliant with the tag policy requirements for this
// account.
ErrCodeConstraintViolationException = "ConstraintViolationException"
// ErrCodeCreateAccountStatusNotFoundException for service response error code
// "CreateAccountStatusNotFoundException".
//
// We can't find an create account request with the CreateAccountRequestId that
// you specified.
ErrCodeCreateAccountStatusNotFoundException = "CreateAccountStatusNotFoundException"
// ErrCodeDestinationParentNotFoundException for service response error code
// "DestinationParentNotFoundException".
//
// We can't find the destination container (a root or OU) with the ParentId
// that you specified.
ErrCodeDestinationParentNotFoundException = "DestinationParentNotFoundException"
// ErrCodeDuplicateAccountException for service response error code
// "DuplicateAccountException".
//
// That account is already present in the specified destination.
ErrCodeDuplicateAccountException = "DuplicateAccountException"
// ErrCodeDuplicateHandshakeException for service response error code
// "DuplicateHandshakeException".
//
// A handshake with the same action and target already exists. For example,
// if you invited an account to join your organization, the invited account
// might already have a pending invitation from this organization. If you intend
// to resend an invitation to an account, ensure that existing handshakes that
// might be considered duplicates are canceled or declined.
ErrCodeDuplicateHandshakeException = "DuplicateHandshakeException"
// ErrCodeDuplicateOrganizationalUnitException for service response error code
// "DuplicateOrganizationalUnitException".
//
// An OU with the same name already exists.
ErrCodeDuplicateOrganizationalUnitException = "DuplicateOrganizationalUnitException"
// ErrCodeDuplicatePolicyAttachmentException for service response error code
// "DuplicatePolicyAttachmentException".
//
// The selected policy is already attached to the specified target.
ErrCodeDuplicatePolicyAttachmentException = "DuplicatePolicyAttachmentException"
// ErrCodeDuplicatePolicyException for service response error code
// "DuplicatePolicyException".
//
// A policy with the same name already exists.
ErrCodeDuplicatePolicyException = "DuplicatePolicyException"
// ErrCodeEffectivePolicyNotFoundException for service response error code
// "EffectivePolicyNotFoundException".
//
// If you ran this action on the management account, this policy type is not
// enabled. If you ran the action on a member account, the account doesn't have
// an effective policy of this type. Contact the administrator of your organization
// about attaching a policy of this type to the account.
ErrCodeEffectivePolicyNotFoundException = "EffectivePolicyNotFoundException"
// ErrCodeFinalizingOrganizationException for service response error code
// "FinalizingOrganizationException".
//
// AWS Organizations couldn't perform the operation because your organization
// hasn't finished initializing. This can take up to an hour. Try again later.
// If after one hour you continue to receive this error, contact AWS Support
// (https://console.aws.amazon.com/support/home#/).
ErrCodeFinalizingOrganizationException = "FinalizingOrganizationException"
// ErrCodeHandshakeAlreadyInStateException for service response error code
// "HandshakeAlreadyInStateException".
//
// The specified handshake is already in the requested state. For example, you
// can't accept a handshake that was already accepted.
ErrCodeHandshakeAlreadyInStateException = "HandshakeAlreadyInStateException"
// ErrCodeHandshakeConstraintViolationException for service response error code
// "HandshakeConstraintViolationException".
//
// The requested operation would violate the constraint identified in the reason
// code.
//
// Some of the reasons in the following list might not be applicable to this
// specific API or operation:
//
// * ACCOUNT_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the limit on
// the number of accounts in an organization. Note that deleted and closed
// accounts still count toward your limit. If you get this exception immediately
// after creating the organization, wait one hour and try again. If after
// an hour it continues to fail with this error, contact AWS Support (https://console.aws.amazon.com/support/home#/).
//
// * ALREADY_IN_AN_ORGANIZATION: The handshake request is invalid because
// the invited account is already a member of an organization.
//
// * HANDSHAKE_RATE_LIMIT_EXCEEDED: You attempted to exceed the number of
// handshakes that you can send in one day.
//
// * INVITE_DISABLED_DURING_ENABLE_ALL_FEATURES: You can't issue new invitations
// to join an organization while it's in the process of enabling all features.
// You can resume inviting accounts after you finalize the process when all
// accounts have agreed to the change.
//
// * ORGANIZATION_ALREADY_HAS_ALL_FEATURES: The handshake request is invalid
// because the organization has already enabled all features.
//
// * ORGANIZATION_FROM_DIFFERENT_SELLER_OF_RECORD: The request failed because
// the account is from a different marketplace than the accounts in the organization.
// For example, accounts with India addresses must be associated with the
// AISPL marketplace. All accounts in an organization must be from the same
// marketplace.
//
// * ORGANIZATION_MEMBERSHIP_CHANGE_RATE_LIMIT_EXCEEDED: You attempted to
// change the membership of an account too quickly after its previous change.
//
// * PAYMENT_INSTRUMENT_REQUIRED: You can't complete the operation with an
// account that doesn't have a payment instrument, such as a credit card,
// associated with it.
ErrCodeHandshakeConstraintViolationException = "HandshakeConstraintViolationException"
// ErrCodeHandshakeNotFoundException for service response error code
// "HandshakeNotFoundException".
//
// We can't find a handshake with the HandshakeId that you specified.
ErrCodeHandshakeNotFoundException = "HandshakeNotFoundException"
// ErrCodeInvalidHandshakeTransitionException for service response error code
// "InvalidHandshakeTransitionException".
//
// You can't perform the operation on the handshake in its current state. For
// example, you can't cancel a handshake that was already accepted or accept
// a handshake that was already declined.
ErrCodeInvalidHandshakeTransitionException = "InvalidHandshakeTransitionException"
// ErrCodeInvalidInputException for service response error code
// "InvalidInputException".
//
// The requested operation failed because you provided invalid values for one
// or more of the request parameters. This exception includes a reason that
// contains additional information about the violated limit:
//
// Some of the reasons in the following list might not be applicable to this
// specific API or operation.
//
// * DUPLICATE_TAG_KEY: Tag keys must be unique among the tags attached to
// the same entity.
//
// * IMMUTABLE_POLICY: You specified a policy that is managed by AWS and
// can't be modified.
//
// * INPUT_REQUIRED: You must include a value for all required parameters.
//
// * INVALID_ENUM: You specified an invalid value.
//
// * INVALID_ENUM_POLICY_TYPE: You specified an invalid policy type string.
//
// * INVALID_FULL_NAME_TARGET: You specified a full name that contains invalid
// characters.
//
// * INVALID_LIST_MEMBER: You provided a list to a parameter that contains
// at least one invalid value.
//
// * INVALID_PAGINATION_TOKEN: Get the value for the NextToken parameter
// from the response to a previous call of the operation.
//
// * INVALID_PARTY_TYPE_TARGET: You specified the wrong type of entity (account,
// organization, or email) as a party.
//
// * INVALID_PATTERN: You provided a value that doesn't match the required
// pattern.
//
// * INVALID_PATTERN_TARGET_ID: You specified a policy target ID that doesn't
// match the required pattern.
//
// * INVALID_ROLE_NAME: You provided a role name that isn't valid. A role
// name can't begin with the reserved prefix AWSServiceRoleFor.
//
// * INVALID_SYNTAX_ORGANIZATION_ARN: You specified an invalid Amazon Resource
// Name (ARN) for the organization.
//
// * INVALID_SYNTAX_POLICY_ID: You specified an invalid policy ID.
//
// * INVALID_SYSTEM_TAGS_PARAMETER: You specified a tag key that is a system
// tag. You cant add, edit, or delete system tag keys because they're
// reserved for AWS use. System tags dont count against your tags per
// resource limit.
//
// * MAX_FILTER_LIMIT_EXCEEDED: You can specify only one filter parameter
// for the operation.
//
// * MAX_LENGTH_EXCEEDED: You provided a string parameter that is longer
// than allowed.
//
// * MAX_VALUE_EXCEEDED: You provided a numeric parameter that has a larger
// value than allowed.
//
// * MIN_LENGTH_EXCEEDED: You provided a string parameter that is shorter
// than allowed.
//
// * MIN_VALUE_EXCEEDED: You provided a numeric parameter that has a smaller
// value than allowed.
//
// * MOVING_ACCOUNT_BETWEEN_DIFFERENT_ROOTS: You can move an account only
// between entities in the same root.
//
// * TARGET_NOT_SUPPORTED: You can't perform the specified operation on that
// target entity.
//
// * UNRECOGNIZED_SERVICE_PRINCIPAL: You specified a service principal that
// isn't recognized.
ErrCodeInvalidInputException = "InvalidInputException"
// ErrCodeMalformedPolicyDocumentException for service response error code
// "MalformedPolicyDocumentException".
//
// The provided policy document doesn't meet the requirements of the specified
// policy type. For example, the syntax might be incorrect. For details about
// service control policy syntax, see Service Control Policy Syntax (https://docs.aws.amazon.com/organizations/latest/userguide/orgs_reference_scp-syntax.html)
// in the AWS Organizations User Guide.
ErrCodeMalformedPolicyDocumentException = "MalformedPolicyDocumentException"
// ErrCodeMasterCannotLeaveOrganizationException for service response error code
// "MasterCannotLeaveOrganizationException".
//
// You can't remove a management account from an organization. If you want the
// management account to become a member account in another organization, you
// must first delete the current organization of the management account.
ErrCodeMasterCannotLeaveOrganizationException = "MasterCannotLeaveOrganizationException"
// ErrCodeOrganizationNotEmptyException for service response error code
// "OrganizationNotEmptyException".
//
// The organization isn't empty. To delete an organization, you must first remove
// all accounts except the management account, delete all OUs, and delete all
// policies.
ErrCodeOrganizationNotEmptyException = "OrganizationNotEmptyException"
// ErrCodeOrganizationalUnitNotEmptyException for service response error code
// "OrganizationalUnitNotEmptyException".
//
// The specified OU is not empty. Move all accounts to another root or to other
// OUs, remove all child OUs, and try the operation again.
ErrCodeOrganizationalUnitNotEmptyException = "OrganizationalUnitNotEmptyException"
// ErrCodeOrganizationalUnitNotFoundException for service response error code
// "OrganizationalUnitNotFoundException".
//
// We can't find an OU with the OrganizationalUnitId that you specified.
ErrCodeOrganizationalUnitNotFoundException = "OrganizationalUnitNotFoundException"
// ErrCodeParentNotFoundException for service response error code
// "ParentNotFoundException".
//
// We can't find a root or OU with the ParentId that you specified.
ErrCodeParentNotFoundException = "ParentNotFoundException"
// ErrCodePolicyChangesInProgressException for service response error code
// "PolicyChangesInProgressException".
//
// Changes to the effective policy are in progress, and its contents can't be
// returned. Try the operation again later.
ErrCodePolicyChangesInProgressException = "PolicyChangesInProgressException"
// ErrCodePolicyInUseException for service response error code
// "PolicyInUseException".
//
// The policy is attached to one or more entities. You must detach it from all
// roots, OUs, and accounts before performing this operation.
ErrCodePolicyInUseException = "PolicyInUseException"
// ErrCodePolicyNotAttachedException for service response error code
// "PolicyNotAttachedException".
//
// The policy isn't attached to the specified target in the specified root.
ErrCodePolicyNotAttachedException = "PolicyNotAttachedException"
// ErrCodePolicyNotFoundException for service response error code
// "PolicyNotFoundException".
//
// We can't find a policy with the PolicyId that you specified.
ErrCodePolicyNotFoundException = "PolicyNotFoundException"
// ErrCodePolicyTypeAlreadyEnabledException for service response error code
// "PolicyTypeAlreadyEnabledException".
//
// The specified policy type is already enabled in the specified root.
ErrCodePolicyTypeAlreadyEnabledException = "PolicyTypeAlreadyEnabledException"
// ErrCodePolicyTypeNotAvailableForOrganizationException for service response error code
// "PolicyTypeNotAvailableForOrganizationException".
//
// You can't use the specified policy type with the feature set currently enabled
// for this organization. For example, you can enable SCPs only after you enable
// all features in the organization. For more information, see Managing AWS
// Organizations Policies (https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies.html#enable_policies_on_root)in
// the AWS Organizations User Guide.
ErrCodePolicyTypeNotAvailableForOrganizationException = "PolicyTypeNotAvailableForOrganizationException"
// ErrCodePolicyTypeNotEnabledException for service response error code
// "PolicyTypeNotEnabledException".
//
// The specified policy type isn't currently enabled in this root. You can't
// attach policies of the specified type to entities in a root until you enable
// that type in the root. For more information, see Enabling All Features in
// Your Organization (https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_support-all-features.html)
// in the AWS Organizations User Guide.
ErrCodePolicyTypeNotEnabledException = "PolicyTypeNotEnabledException"
// ErrCodeRootNotFoundException for service response error code
// "RootNotFoundException".
//
// We can't find a root with the RootId that you specified.
ErrCodeRootNotFoundException = "RootNotFoundException"
// ErrCodeServiceException for service response error code
// "ServiceException".
//
// AWS Organizations can't complete your request because of an internal service
// error. Try again later.
ErrCodeServiceException = "ServiceException"
// ErrCodeSourceParentNotFoundException for service response error code
// "SourceParentNotFoundException".
//
// We can't find a source root or OU with the ParentId that you specified.
ErrCodeSourceParentNotFoundException = "SourceParentNotFoundException"
// ErrCodeTargetNotFoundException for service response error code
// "TargetNotFoundException".
//
// We can't find a root, OU, account, or policy with the TargetId that you specified.
ErrCodeTargetNotFoundException = "TargetNotFoundException"
// ErrCodeTooManyRequestsException for service response error code
// "TooManyRequestsException".
//
// You have sent too many requests in too short a period of time. The quota
// helps protect against denial-of-service attacks. Try again later.
//
// For information about quotas that affect AWS Organizations, see Quotas for
// AWS Organizations (https://docs.aws.amazon.com/organizations/latest/userguide/orgs_reference_limits.html)in
// the AWS Organizations User Guide.
ErrCodeTooManyRequestsException = "TooManyRequestsException"
// ErrCodeUnsupportedAPIEndpointException for service response error code
// "UnsupportedAPIEndpointException".
//
// This action isn't available in the current AWS Region.
ErrCodeUnsupportedAPIEndpointException = "UnsupportedAPIEndpointException"
)
var exceptionFromCode = map[string]func(protocol.ResponseMetadata) error{
"AWSOrganizationsNotInUseException": newErrorAWSOrganizationsNotInUseException,
"AccessDeniedException": newErrorAccessDeniedException,
"AccessDeniedForDependencyException": newErrorAccessDeniedForDependencyException,
"AccountAlreadyRegisteredException": newErrorAccountAlreadyRegisteredException,
"AccountNotFoundException": newErrorAccountNotFoundException,
"AccountNotRegisteredException": newErrorAccountNotRegisteredException,
"AccountOwnerNotVerifiedException": newErrorAccountOwnerNotVerifiedException,
"AlreadyInOrganizationException": newErrorAlreadyInOrganizationException,
"ChildNotFoundException": newErrorChildNotFoundException,
"ConcurrentModificationException": newErrorConcurrentModificationException,
"ConstraintViolationException": newErrorConstraintViolationException,
"CreateAccountStatusNotFoundException": newErrorCreateAccountStatusNotFoundException,
"DestinationParentNotFoundException": newErrorDestinationParentNotFoundException,
"DuplicateAccountException": newErrorDuplicateAccountException,
"DuplicateHandshakeException": newErrorDuplicateHandshakeException,
"DuplicateOrganizationalUnitException": newErrorDuplicateOrganizationalUnitException,
"DuplicatePolicyAttachmentException": newErrorDuplicatePolicyAttachmentException,
"DuplicatePolicyException": newErrorDuplicatePolicyException,
"EffectivePolicyNotFoundException": newErrorEffectivePolicyNotFoundException,
"FinalizingOrganizationException": newErrorFinalizingOrganizationException,
"HandshakeAlreadyInStateException": newErrorHandshakeAlreadyInStateException,
"HandshakeConstraintViolationException": newErrorHandshakeConstraintViolationException,
"HandshakeNotFoundException": newErrorHandshakeNotFoundException,
"InvalidHandshakeTransitionException": newErrorInvalidHandshakeTransitionException,
"InvalidInputException": newErrorInvalidInputException,
"MalformedPolicyDocumentException": newErrorMalformedPolicyDocumentException,
"MasterCannotLeaveOrganizationException": newErrorMasterCannotLeaveOrganizationException,
"OrganizationNotEmptyException": newErrorOrganizationNotEmptyException,
"OrganizationalUnitNotEmptyException": newErrorOrganizationalUnitNotEmptyException,
"OrganizationalUnitNotFoundException": newErrorOrganizationalUnitNotFoundException,
"ParentNotFoundException": newErrorParentNotFoundException,
"PolicyChangesInProgressException": newErrorPolicyChangesInProgressException,
"PolicyInUseException": newErrorPolicyInUseException,
"PolicyNotAttachedException": newErrorPolicyNotAttachedException,
"PolicyNotFoundException": newErrorPolicyNotFoundException,
"PolicyTypeAlreadyEnabledException": newErrorPolicyTypeAlreadyEnabledException,
"PolicyTypeNotAvailableForOrganizationException": newErrorPolicyTypeNotAvailableForOrganizationException,
"PolicyTypeNotEnabledException": newErrorPolicyTypeNotEnabledException,
"RootNotFoundException": newErrorRootNotFoundException,
"ServiceException": newErrorServiceException,
"SourceParentNotFoundException": newErrorSourceParentNotFoundException,
"TargetNotFoundException": newErrorTargetNotFoundException,
"TooManyRequestsException": newErrorTooManyRequestsException,
"UnsupportedAPIEndpointException": newErrorUnsupportedAPIEndpointException,
}
+103
View File
@@ -0,0 +1,103 @@
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package organizations
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol"
"github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
)
// Organizations provides the API operation methods for making requests to
// AWS Organizations. See this package's package overview docs
// for details on the service.
//
// Organizations methods are safe to use concurrently. It is not safe to
// modify mutate any of the struct's properties though.
type Organizations struct {
*client.Client
}
// Used for custom client initialization logic
var initClient func(*client.Client)
// Used for custom request initialization logic
var initRequest func(*request.Request)
// Service information constants
const (
ServiceName = "organizations" // Name of service.
EndpointsID = ServiceName // ID to lookup a service endpoint with.
ServiceID = "Organizations" // ServiceID is a unique identifier of a specific service.
)
// New creates a new instance of the Organizations client with a session.
// If additional configuration is needed for the client instance use the optional
// aws.Config parameter to add your extra config.
//
// Example:
// mySession := session.Must(session.NewSession())
//
// // Create a Organizations client from just a session.
// svc := organizations.New(mySession)
//
// // Create a Organizations client with additional configuration
// svc := organizations.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
func New(p client.ConfigProvider, cfgs ...*aws.Config) *Organizations {
c := p.ClientConfig(EndpointsID, cfgs...)
return newClient(*c.Config, c.Handlers, c.PartitionID, c.Endpoint, c.SigningRegion, c.SigningName)
}
// newClient creates, initializes and returns a new service client instance.
func newClient(cfg aws.Config, handlers request.Handlers, partitionID, endpoint, signingRegion, signingName string) *Organizations {
svc := &Organizations{
Client: client.New(
cfg,
metadata.ClientInfo{
ServiceName: ServiceName,
ServiceID: ServiceID,
SigningName: signingName,
SigningRegion: signingRegion,
PartitionID: partitionID,
Endpoint: endpoint,
APIVersion: "2016-11-28",
JSONVersion: "1.1",
TargetPrefix: "AWSOrganizationsV20161128",
},
handlers,
),
}
// Handlers
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler)
svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler)
svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler)
svc.Handlers.UnmarshalError.PushBackNamed(
protocol.NewUnmarshalErrorHandler(jsonrpc.NewUnmarshalTypedError(exceptionFromCode)).NamedHandler(),
)
// Run custom client initialization if present
if initClient != nil {
initClient(svc.Client)
}
return svc
}
// newRequest creates a new request for a Organizations operation and runs any
// custom request initialization.
func (c *Organizations) newRequest(op *request.Operation, params, data interface{}) *request.Request {
req := c.NewRequest(op, params, data)
// Run custom request initialization if present
if initRequest != nil {
initRequest(req)
}
return req
}
+3 -2
View File
@@ -177,6 +177,7 @@ github.com/aws/aws-sdk-go/service/ec2
github.com/aws/aws-sdk-go/service/elasticache
github.com/aws/aws-sdk-go/service/elbv2
github.com/aws/aws-sdk-go/service/iam
github.com/aws/aws-sdk-go/service/organizations
github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi
github.com/aws/aws-sdk-go/service/route53
github.com/aws/aws-sdk-go/service/s3
@@ -1142,7 +1143,7 @@ yunion.io/x/log/hooks
yunion.io/x/ovsdb/cli_util
yunion.io/x/ovsdb/schema/ovn_nb
yunion.io/x/ovsdb/types
# yunion.io/x/pkg v0.0.0-20210109071527-7e72daf56747
# yunion.io/x/pkg v0.0.0-20210218105412-13a69f60034c
yunion.io/x/pkg/errors
yunion.io/x/pkg/gotypes
yunion.io/x/pkg/prettytable
@@ -1176,7 +1177,7 @@ yunion.io/x/pkg/util/workqueue
yunion.io/x/pkg/utils
# yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
yunion.io/x/s3cli
# yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb
# yunion.io/x/sqlchemy v0.0.0-20210204030051-4fb14f92a88f
yunion.io/x/sqlchemy
# yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce
yunion.io/x/structarg
+9 -3
View File
@@ -15,6 +15,7 @@
package utils
import (
"context"
"fmt"
"time"
)
@@ -86,8 +87,9 @@ type FibonacciRetrier struct {
// If RetryFunc returns with done being true. err will also be what RetryFunc returns
//
// Otherwise Start will return with done being false and err of type
// FibonacciRetrierError with last err returned by RetryFunc wrapped in
func (fibr *FibonacciRetrier) Start() (done bool, err error) {
// FibonacciRetrierError with last err returned by RetryFunc wrapped in, or
// ctx.Err() if it's done
func (fibr *FibonacciRetrier) Start(ctx context.Context) (done bool, err error) {
fibr.tried = 0
fibr.startTime = time.Now()
defer func() {
@@ -110,7 +112,11 @@ func (fibr *FibonacciRetrier) Start() (done bool, err error) {
// maxTries 1 2 3 4 5 6 7
// T0 1 2 3 5 8 13
// Elapse 0 1 3 6 11 19 32
time.Sleep(fibr.T0)
select {
case <-time.After(fibr.T0):
case <-ctx.Done():
return false, ctx.Err()
}
}
}
+3
View File
@@ -1,5 +1,8 @@
# sqlchemy
[![CircleCI](https://circleci.com/gh/yunionio/sqlchemy.svg?style=svg)](https://circleci.com/gh/yunionio/sqlchemy)
[![Go Report Card](https://goreportcard.com/badge/github.com/yunionio/sqlchemy)](https://goreportcard.com/report/github.com/yunionio/sqlchemy)
A lightweight golang ORM library inspired by python sqlalchemy.
Features