func (r *ReconcileAccount) asyncRegionInit(reqLogger logr.Logger, currentAcctInstance *awsv1alpha1.Account, creds *sts.AssumeRoleOutput, regionAMIs map[string]awsv1alpha1.AmiSpec, regionsEnabledInAccount []v1alpha1.AwsRegions) {
	r.InitializeSupportedRegions(reqLogger, currentAcctInstance, regionsEnabledInAccount, creds, regionAMIs)
	if currentAcctInstance.IsBYOC() {
		utils.SetAccountStatus(currentAcctInstance, "BYOC Account Ready", awsv1alpha1.AccountReady, AccountReady)
	} else {
		if currentAcctInstance.GetCondition(awsv1alpha1.AccountReady) != nil {
			msg := "Account support case already resolved; Account Ready"
			utils.SetAccountStatus(currentAcctInstance, msg, awsv1alpha1.AccountReady, AccountReady)
			reqLogger.Info(msg)
		} else {
			msg := "Account pending AWS limits verification"
			utils.SetAccountStatus(currentAcctInstance, msg, awsv1alpha1.AccountPendingVerification, AccountPendingVerification)
			reqLogger.Info(msg)
		}
	}
	if err := r.statusUpdate(currentAcctInstance); err != nil {
		reqLogger.Error(err, "asyncRegionInit failed to update status")
	}
}
asyncRegionInit initializes supported regions by creating and destroying an instance in each.
Upon completion, it *always* sets the Account status to either Ready or PendingVerification.
There is no mechanism for this func to report errors to its parent. The only error paths
currently possible are:
- The Status update fails.
- This goroutine dies in some horrible and unpredictable way.
In either case we would expect the main reconciler to eventually notice that the Account has
been in the InitializingRegions state for too long, and set it to Failed.
package account
import (
	"context"
	"errors"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/organizations"
	"github.com/aws/aws-sdk-go/service/sts"
	"github.com/go-logr/logr"
	"github.com/openshift/aws-account-operator/pkg/controller/utils"
	"github.com/rkt/rkt/tests/testutils/logger"
	corev1 "k8s.io/api/core/v1"
	k8serr "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/controller"
	"sigs.k8s.io/controller-runtime/pkg/handler"
	logf "sigs.k8s.io/controller-runtime/pkg/log"
	"sigs.k8s.io/controller-runtime/pkg/manager"
	"sigs.k8s.io/controller-runtime/pkg/reconcile"
	"sigs.k8s.io/controller-runtime/pkg/source"
	"github.com/openshift/aws-account-operator/pkg/apis/aws/v1alpha1"
	awsv1alpha1 "github.com/openshift/aws-account-operator/pkg/apis/aws/v1alpha1"
	"github.com/openshift/aws-account-operator/pkg/awsclient"
	controllerutils "github.com/openshift/aws-account-operator/pkg/controller/utils"
	totalaccountwatcher "github.com/openshift/aws-account-operator/pkg/totalaccountwatcher"
)
var log = logf.Log.WithName("controller_account")
const (
	vCPUQuotaCode = "L-1216C47A"
	vCPUServiceCode = "ec2"
	createPendTime = utils.WaitTime * time.Minute
	regionInitTime = (time.Minute * utils.WaitTime * time.Duration(2)) + time.Minute
	AccountPending = "Pending"
	AccountCreating = "Creating"
	AccountFailed = "Failed"
	AccountInitializingRegions = "InitializingRegions"
	AccountReady = "Ready"
	AccountPendingVerification = "PendingVerification"
	byocRole = "BYOCAdminAccess"
	adminAccessArn = "arn:aws:iam::aws:policy/AdministratorAccess"
	iamUserNameUHC = "osdManagedAdmin"
	controllerName = "account"
)
func Add(mgr manager.Manager) error {
	return add(mgr, newReconciler(mgr))
}
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
	reconciler := &ReconcileAccount{
		Client:           utils.NewClientWithMetricsOrDie(log, mgr, controllerName),
		scheme:           mgr.GetScheme(),
		awsClientBuilder: &awsclient.Builder{},
	}
	configMap, err := controllerutils.GetOperatorConfigMap(reconciler.Client)
	if err != nil {
		log.Error(err, "failed retrieving configmap")
	}
	hiveName, ok := configMap.Data["shard-name"]
	if !ok {
		log.Error(err, "shard-name key not available in configmap")
	}
	reconciler.shardName = hiveName
	return utils.NewReconcilerWithMetrics(reconciler, controllerName)
}
func add(mgr manager.Manager, r reconcile.Reconciler) error {
	c, err := controller.New("account-controller", mgr, controller.Options{Reconciler: r})
	if err != nil {
		return err
	}
	err = c.Watch(&source.Kind{Type: &awsv1alpha1.Account{}}, &handler.EnqueueRequestForObject{})
	if err != nil {
		return err
	}
	return nil
}
var _ reconcile.Reconciler = &ReconcileAccount{}
type ReconcileAccount struct {
	Client           client.Client
	scheme           *runtime.Scheme
	awsClientBuilder awsclient.IBuilder
	shardName        string
}
func (r *ReconcileAccount) Reconcile(request reconcile.Request) (reconcile.Result, error) {
	reqLogger := log.WithValues("Controller", controllerName, "Request.Namespace", request.Namespace, "Request.Name", request.Name)
	currentAcctInstance := &awsv1alpha1.Account{}
	err := r.Client.Get(context.TODO(), request.NamespacedName, currentAcctInstance)
	if err != nil {
		if k8serr.IsNotFound(err) {
			return reconcile.Result{}, nil
		}
		return reconcile.Result{}, err
	}
	awsSetupClient, err := r.awsClientBuilder.GetClient(controllerName, r.Client, awsclient.NewAwsClientInput{
		SecretName: utils.AwsSecretName,
		NameSpace:  awsv1alpha1.AccountCrNamespace,
		AwsRegion:  "us-east-1",
	})
	if err != nil {
		reqLogger.Error(err, "failed building operator AWS client")
		return reconcile.Result{}, err
	}
	if currentAcctInstance.IsPendingDeletion() {
		if currentAcctInstance.Spec.ManualSTSMode {
			err := r.removeFinalizer(currentAcctInstance, awsv1alpha1.AccountFinalizer)
			if err != nil {
				reqLogger.Error(err, "Failed removing account finalizer")
			}
			return reconcile.Result{}, err
		}
		var awsClient awsclient.Client
		if currentAcctInstance.IsBYOC() {
			roleToAssume := getAssumeRole(currentAcctInstance)
			awsClient, _, err = r.assumeRole(reqLogger, currentAcctInstance, awsSetupClient, roleToAssume, "")
			if err != nil {
				reqLogger.Error(err, "failed building BYOC client from assume_role")
				if aerr, ok := err.(awserr.Error); ok {
					switch aerr.Code() {
					case "AccessDenied":
						if currentAcctInstance.IsBYOC() {
							err = r.removeFinalizer(currentAcctInstance, awsv1alpha1.AccountFinalizer)
							if err != nil {
								reqLogger.Error(err, "failed removing account finalizer")
								return reconcile.Result{}, err
							}
							reqLogger.Info("Finalizer Removed on CCS Account with ACCESSDENIED")
							return reconcile.Result{}, nil
						}
					}
				}
				return reconcile.Result{}, err
			}
		} else {
			awsClient, _, err = r.assumeRole(reqLogger, currentAcctInstance, awsSetupClient, awsv1alpha1.AccountOperatorIAMRole, "")
			if err != nil {
				reqLogger.Error(err, "failed building AWS client from assume_role")
				return reconcile.Result{}, err
			}
		}
		r.finalizeAccount(reqLogger, awsClient, currentAcctInstance)
		if currentAcctInstance.IsBYOCPendingDeletionWithFinalizer() {
			reqLogger.Info("removing account finalizer")
			err = r.removeFinalizer(currentAcctInstance, awsv1alpha1.AccountFinalizer)
			if err != nil {
				reqLogger.Error(err, "failed removing account finalizer")
				return reconcile.Result{}, err
			}
		}
		return reconcile.Result{}, nil
	}
	if currentAcctInstance.IsFailed() {
		reqLogger.Info(fmt.Sprintf("Account %s is failed. Ignoring.", currentAcctInstance.Name))
		return reconcile.Result{}, nil
	}
	if currentAcctInstance.IsInitializingRegions() {
		return r.handleAccountInitializingRegions(reqLogger, currentAcctInstance)
	}
	if newBYOCAccount(currentAcctInstance) {
		var result reconcile.Result
		var initErr error
		result, initErr = r.initializeNewCCSAccount(reqLogger, currentAcctInstance)
		if initErr != nil {
			_, stateErr := r.setAccountFailed(
				reqLogger,
				currentAcctInstance,
				awsv1alpha1.AccountCreationFailed,
				initErr.Error(),
				"Failed to initialize new CCS account",
				AccountFailed,
			)
			if stateErr != nil {
				reqLogger.Error(stateErr, "failed setting account state", "desiredState", AccountFailed)
			}
			reqLogger.Error(initErr, "failed initializing new CCS account")
			return result, initErr
		}
		utils.SetAccountStatus(currentAcctInstance, AccountCreating, awsv1alpha1.AccountCreating, AccountCreating)
		updateErr := r.statusUpdate(currentAcctInstance)
		if updateErr != nil {
			reqLogger.Info("failed updating account state, retrying", "desired state", AccountCreating)
			return reconcile.Result{}, updateErr
		}
	} else {
		if currentAcctInstance.IsPendingVerification() {
			return r.handleNonCCSPendingVerification(reqLogger, currentAcctInstance, awsSetupClient)
		}
		if currentAcctInstance.IsReadyUnclaimedAndHasClaimLink() {
			currentAcctInstance.Status.Claimed = true
			return reconcile.Result{}, r.statusUpdate(currentAcctInstance)
		}
		if currentAcctInstance.IsCreating() && utils.CreationConditionOlderThan(*currentAcctInstance, createPendTime) {
			errMsg := fmt.Sprintf("Creation pending for longer than %d minutes", utils.WaitTime)
			_, stateErr := r.setAccountFailed(
				reqLogger,
				currentAcctInstance,
				v1alpha1.AccountCreationFailed,
				"CreationTimeout",
				errMsg,
				AccountFailed,
			)
			if stateErr != nil {
				reqLogger.Error(stateErr, "failed setting account state", "desiredState", AccountFailed)
				return reconcile.Result{}, stateErr
			}
			return reconcile.Result{}, errors.New(errMsg)
		}
		if currentAcctInstance.IsUnclaimedAndHasNoState() {
			if !currentAcctInstance.HasAwsAccountID() {
				if !totalaccountwatcher.TotalAccountWatcher.AccountsCanBeCreated() {
					reqLogger.Error(awsv1alpha1.ErrAwsAccountLimitExceeded, "AWS Account limit reached")
					return reconcile.Result{Requeue: true, RequeueAfter: time.Duration(5) * time.Minute}, nil
				}
				if err := r.nonCCSAssignAccountID(reqLogger, currentAcctInstance, awsSetupClient); err != nil {
					return reconcile.Result{}, err
				}
			} else {
				utils.SetAccountStatus(currentAcctInstance, "AWS account already created", awsv1alpha1.AccountCreating, AccountCreating)
				err = r.statusUpdate(currentAcctInstance)
				if err != nil {
					return reconcile.Result{}, err
				}
			}
		}
	}
	configMap, err := controllerutils.GetOperatorConfigMap(r.Client)
	stringRegions, ok := configMap.Data["regions"]
	if !ok {
		err = awsv1alpha1.ErrInvalidConfigMap
		return reconcile.Result{}, err
	}
	if err != nil {
		reqLogger.Error(err, "failed getting regions from configmap data")
		return reconcile.Result{}, err
	}
	regionAMIs := processConfigMapRegions(stringRegions)
	if currentAcctInstance.ReadyForInitialization() {
		reqLogger.Info("initializing account", "awsAccountID", currentAcctInstance.Spec.AwsAccountID)
		if currentAcctInstance.Spec.ManualSTSMode {
			accountClaim, acctClaimErr := r.getAccountClaim(currentAcctInstance)
			if acctClaimErr != nil {
				reqLogger.Error(acctClaimErr, "unable to get accountclaim for sts account")
				utils.SetAccountClaimStatus(
					accountClaim,
					"Failed to get AccountClaim for CSS account",
					"FailedRetrievingAccountClaim",
					awsv1alpha1.ClientError,
					awsv1alpha1.ClaimStatusError,
				)
				err := r.Client.Status().Update(context.TODO(), accountClaim)
				if err != nil {
					reqLogger.Error(err, "failed to update accountclaim status")
				}
				return reconcile.Result{}, acctClaimErr
			}
			_, creds, err := r.getSTSClient(reqLogger, accountClaim, awsSetupClient)
			if err != nil {
				reqLogger.Error(err, "error getting sts client to initialize regions")
				return reconcile.Result{}, err
			}
			if err = r.initializeRegions(reqLogger, currentAcctInstance, creds, regionAMIs); err != nil {
				return reconcile.Result{}, err
			}
			return reconcile.Result{}, nil
		}
		if !utils.AccountCRHasIAMUserIDLabel(currentAcctInstance) {
			utils.AddLabels(
				currentAcctInstance,
				utils.GenerateLabel(
					awsv1alpha1.IAMUserIDLabel,
					utils.GenerateShortUID(),
				),
			)
			return reconcile.Result{Requeue: true}, r.Client.Update(context.TODO(), currentAcctInstance)
		}
		awsAssumedRoleClient, creds, err := r.handleCreateAdminAccessRole(reqLogger, currentAcctInstance, awsSetupClient)
		if err != nil {
			return reconcile.Result{}, err
		}
		iamUserUHC := fmt.Sprintf("%s-%s", iamUserNameUHC, currentAcctInstance.Labels[awsv1alpha1.IAMUserIDLabel])
		secretName, err := r.BuildIAMUser(reqLogger, awsAssumedRoleClient, currentAcctInstance, iamUserUHC, request.Namespace)
		if err != nil {
			reason, errType := getBuildIAMUserErrorReason(err)
			errMsg := fmt.Sprintf("Failed to build IAM UHC user %s: %s", iamUserUHC, err)
			_, stateErr := r.setAccountFailed(
				reqLogger,
				currentAcctInstance,
				errType,
				reason,
				errMsg,
				AccountFailed,
			)
			if stateErr != nil {
				reqLogger.Error(err, "failed setting account state", "desiredState", AccountFailed)
			}
			return reconcile.Result{}, err
		}
		currentAcctInstance.Spec.IAMUserSecret = *secretName
		err = r.accountSpecUpdate(reqLogger, currentAcctInstance)
		if err != nil {
			return reconcile.Result{}, err
		}
		if err = r.initializeRegions(reqLogger, currentAcctInstance, creds, regionAMIs); err != nil {
			return reconcile.Result{}, err
		}
	}
	return reconcile.Result{}, nil
}
func (r *ReconcileAccount) handleAccountInitializingRegions(reqLogger logr.Logger, currentAcctInstance *awsv1alpha1.Account) (reconcile.Result, error) {
	irCond := currentAcctInstance.GetCondition(awsv1alpha1.AccountInitializingRegions)
	if irCond == nil {
		errMsg := "Unexpectedly couldn't find the InitializingRegions Condition"
		_, stateErr := r.setAccountFailed(
			reqLogger,
			currentAcctInstance,
			awsv1alpha1.AccountInternalError,
			"MissingCondition",
			errMsg,
			AccountFailed,
		)
		return reconcile.Result{}, stateErr
	}
	if irCond.LastTransitionTime.Before(utils.GetOperatorStartTime()) {
		msg := "Recovering from stale region initialization."
		utils.SetAccountCondition(
			currentAcctInstance.Status.Conditions,
			awsv1alpha1.AccountInitializingRegions,
			corev1.ConditionFalse,
			AccountInitializingRegions,
			msg,
			utils.UpdateConditionAlways,
			currentAcctInstance.Spec.BYOC)
		utils.SetAccountStatus(currentAcctInstance, msg, v1alpha1.AccountCreating, AccountCreating)
		return reconcile.Result{Requeue: true}, r.statusUpdate(currentAcctInstance)
	}
	if time.Since(irCond.LastTransitionTime.Time) > regionInitTime {
		errMsg := fmt.Sprintf("Initializing regions for longer than %d seconds", regionInitTime/time.Second)
		_, stateErr := r.setAccountFailed(
			reqLogger,
			currentAcctInstance,
			awsv1alpha1.AccountCreationFailed,
			"RegionInitializationTimeout",
			errMsg,
			AccountFailed,
		)
		return reconcile.Result{}, stateErr
	}
	reqLogger.Info(fmt.Sprintf("Account %s is initializing regions. Ignoring.", currentAcctInstance.Name))
	return reconcile.Result{}, nil
}
func (r *ReconcileAccount) handleNonCCSPendingVerification(reqLogger logr.Logger, currentAcctInstance *awsv1alpha1.Account, awsSetupClient awsclient.Client) (reconcile.Result, error) {
	if !currentAcctInstance.HasSupportCaseID() {
		switch utils.DetectDevMode {
		case utils.DevModeProduction:
			caseID, err := createCase(reqLogger, currentAcctInstance, awsSetupClient)
			if err != nil {
				return reconcile.Result{}, err
			}
			reqLogger.Info("case created", "CaseID", caseID)
			currentAcctInstance.Status.SupportCaseID = caseID
			utils.SetAccountStatus(currentAcctInstance, "Account pending verification in AWS", awsv1alpha1.AccountPendingVerification, AccountPendingVerification)
			err = r.statusUpdate(currentAcctInstance)
			if err != nil {
				reqLogger.Error(err, "failed to update account state, retrying", "desired state", AccountPendingVerification)
				return reconcile.Result{}, err
			}
			randomInterval, err := strconv.Atoi(currentAcctInstance.Spec.AwsAccountID)
			if err != nil {
				reqLogger.Error(err, "failed converting AwsAccountID string to int")
				return reconcile.Result{}, err
			}
			randomInterval %= 30
			return reconcile.Result{RequeueAfter: time.Duration(intervalAfterCaseCreationSecs+randomInterval) * time.Second}, nil
		default:
			log.Info("Running in development mode, Skipping Support Case Creation.")
		}
	}
	var resolved bool
	switch utils.DetectDevMode {
	case utils.DevModeProduction:
		resolvedScoped, err := checkCaseResolution(reqLogger, currentAcctInstance.Status.SupportCaseID, awsSetupClient)
		if err != nil {
			reqLogger.Error(err, "Error checking for Case Resolution")
			return reconcile.Result{}, err
		}
		resolved = resolvedScoped
	default:
		log.Info("Running in development mode, Skipping case resolution check")
		resolved = true
	}
	if resolved {
		reqLogger.Info("case resolved", "caseID", currentAcctInstance.Status.SupportCaseID)
		utils.SetAccountStatus(currentAcctInstance, "Account ready to be claimed", awsv1alpha1.AccountReady, AccountReady)
		return reconcile.Result{}, r.statusUpdate(currentAcctInstance)
	}
	reqLogger.Info("case not yet resolved, retrying", "caseID", currentAcctInstance.Status.SupportCaseID, "retry delay", intervalBetweenChecksMinutes)
	return reconcile.Result{RequeueAfter: intervalBetweenChecksMinutes * time.Minute}, nil
}
func (r *ReconcileAccount) finalizeAccount(reqLogger logr.Logger, awsClient awsclient.Client, account *awsv1alpha1.Account) {
	reqLogger.Info("Finalizing Account CR")
	if !account.Spec.ManualSTSMode && utils.AccountCRHasIAMUserIDLabel(account) {
		err := CleanUpIAM(reqLogger, awsClient, account)
		if err != nil {
			reqLogger.Error(err, "Failed to delete IAM user during finalizer cleanup")
		} else {
			reqLogger.Info(fmt.Sprintf("Account: %s has no label", account.Name))
		}
	}
}
func (r *ReconcileAccount) accountSpecUpdate(reqLogger logr.Logger, account *awsv1alpha1.Account) error {
	err := r.Client.Update(context.TODO(), account)
	if err != nil {
		reqLogger.Error(err, fmt.Sprintf("Account spec update for %s failed", account.Name))
	}
	return err
}
func (r *ReconcileAccount) nonCCSAssignAccountID(reqLogger logr.Logger, currentAcctInstance *awsv1alpha1.Account, awsSetupClient awsclient.Client) error {
	var awsAccountID string
	switch utils.DetectDevMode {
	case utils.DevModeProduction:
		var err error
		awsAccountID, err = r.BuildAccount(reqLogger, awsSetupClient, currentAcctInstance)
		if err != nil {
			return err
		}
	default:
		log.Info("Running in development mode, skipping account creation")
		awsAccountID = "123456789012"
	}
	utils.SetAccountStatus(currentAcctInstance, AccountCreating, awsv1alpha1.AccountCreating, AccountCreating)
	err := r.statusUpdate(currentAcctInstance)
	if err != nil {
		return err
	}
	if utils.DetectDevMode != utils.DevModeProduction {
		log.Info("Running in development mode, manually creating a case ID number: 11111111")
		currentAcctInstance.Status.SupportCaseID = "11111111"
	}
	currentAcctInstance.Spec.AwsAccountID = awsAccountID
	err = r.tagAccount(reqLogger, awsSetupClient, awsAccountID)
	if err != nil {
		reqLogger.Info("Unable to tag aws account.", "account", currentAcctInstance.Name, "AWSAccountID", awsAccountID, "Error", error.Error(err))
	}
	return r.accountSpecUpdate(reqLogger, currentAcctInstance)
}
func (r *ReconcileAccount) tagAccount(reqLogger logr.Logger, awsSetupClient awsclient.Client, awsAccountID string) error {
	inputTag := &organizations.TagResourceInput{
		ResourceId: aws.String(awsAccountID),
		Tags: []*organizations.Tag{
			{
				Key:   aws.String("owner"),
				Value: aws.String(r.shardName),
			},
		},
	}
	_, err := awsSetupClient.TagResource(inputTag)
	if err != nil {
		return err
	}
	return nil
}
func (r *ReconcileAccount) assumeRole(
	reqLogger logr.Logger,
	currentAcctInstance *awsv1alpha1.Account,
	awsSetupClient awsclient.Client,
	roleToAssume string,
	ccsRoleID string) (awsclient.Client, *sts.AssumeRoleOutput, error) {
	var roleArn = fmt.Sprintf("arn:aws:iam::%s:role/%s", currentAcctInstance.Spec.AwsAccountID, roleToAssume)
	var roleSessionName = "awsAccountOperator"
	var creds *sts.AssumeRoleOutput
	var credsErr error
	for i := 0; i < 10; i++ {
		creds, credsErr = getSTSCredentials(reqLogger, awsSetupClient, roleArn, "", roleSessionName)
		if credsErr != nil {
			reason := ""
			if aerr, ok := credsErr.(awserr.Error); ok {
				reason = aerr.Code()
			}
			errMsg := fmt.Sprintf("Failed to create STS Credentials for account ID %s: %s", currentAcctInstance.Spec.AwsAccountID, credsErr)
			_, stateErr := r.setAccountFailed(
				reqLogger,
				currentAcctInstance,
				awsv1alpha1.AccountClientError,
				reason,
				errMsg,
				AccountFailed,
			)
			if stateErr != nil {
				reqLogger.Error(stateErr, "failed setting account state", "desiredState", AccountFailed)
			}
			return nil, nil, credsErr
		}
		match, _ := matchSubstring(ccsRoleID, *creds.AssumedRoleUser.AssumedRoleId)
		if ccsRoleID != "" && !match {
			reqLogger.Info(fmt.Sprintf("Assumed RoleID:Session string does not match new RoleID: %s, %s", *creds.AssumedRoleUser.AssumedRoleId, ccsRoleID))
			reqLogger.Info(fmt.Sprintf("Sleeping %d seconds", i))
			time.Sleep(time.Duration(i) * time.Second)
		} else {
			break
		}
	}
	awsAssumedRoleClient, err := r.awsClientBuilder.GetClient(controllerName, r.Client, awsclient.NewAwsClientInput{
		AwsCredsSecretIDKey:     *creds.Credentials.AccessKeyId,
		AwsCredsSecretAccessKey: *creds.Credentials.SecretAccessKey,
		AwsToken:                *creds.Credentials.SessionToken,
		AwsRegion:               "us-east-1",
	})
	if err != nil {
		logger.Error(err, "Failed to assume role")
		reqLogger.Info(err.Error())
		errMsg := "Message Failed creating AWS Client with Assumed Role"
		_, stateErr := r.setAccountFailed(
			reqLogger,
			currentAcctInstance,
			awsv1alpha1.AccountClientError,
			"AWSClientCreationFailed",
			errMsg,
			AccountFailed,
		)
		if stateErr != nil {
			reqLogger.Error(err, "failed setting account state", "desiredState", AccountFailed)
		}
		return nil, nil, err
	}
	return awsAssumedRoleClient, creds, nil
}
func (r *ReconcileAccount) initializeRegions(reqLogger logr.Logger, currentAcctInstance *awsv1alpha1.Account, creds *sts.AssumeRoleOutput, regionAMIs map[string]awsv1alpha1.AmiSpec) error {
	awsClient, err := r.awsClientBuilder.GetClient(controllerName, r.Client, awsclient.NewAwsClientInput{
		AwsCredsSecretIDKey:     *creds.Credentials.AccessKeyId,
		AwsCredsSecretAccessKey: *creds.Credentials.SecretAccessKey,
		AwsToken:                *creds.Credentials.SessionToken,
		AwsRegion:               awsv1alpha1.AwsUSEastOneRegion,
	})
	if err != nil {
		connErr := fmt.Sprintf("unable to connect to default region %s", awsv1alpha1.AwsUSEastOneRegion)
		reqLogger.Error(err, connErr)
		return err
	}
	regionsEnabledInAccount, err := awsClient.DescribeRegions(&ec2.DescribeRegionsInput{
		AllRegions: aws.Bool(false),
	})
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			if aerr.Code() == "OptInRequired" {
				return nil
			}
		}
		reqLogger.Error(err, "Failed to retrieve list of regions enabled in this account.")
		return err
	}
	utils.SetAccountStatus(currentAcctInstance, "Initializing Regions", awsv1alpha1.AccountInitializingRegions, AccountInitializingRegions)
	if err := r.statusUpdate(currentAcctInstance); err != nil {
		return err
	}
	if !currentAcctInstance.IsBYOC() {
		go r.asyncRegionInit(reqLogger, currentAcctInstance, creds, regionAMIs, castAWSRegionType(regionsEnabledInAccount.Regions))
		return nil
	}
	accountClaim, acctClaimErr := r.getAccountClaim(currentAcctInstance)
	if acctClaimErr != nil {
		reqLogger.Info("Accountclaim not found")
		return acctClaimErr
	}
	for _, wantedRegion := range accountClaim.Spec.Aws.Regions {
		found := false
		for _, enabledRegion := range regionsEnabledInAccount.Regions {
			if wantedRegion.Name == *enabledRegion.RegionName {
				found = true
			}
		}
		if !found {
			utils.SetAccountStatus(
				currentAcctInstance,
				fmt.Sprintf("AWS region %s is not supported for AWS account %s", wantedRegion, currentAcctInstance.Name),
				awsv1alpha1.AccountInitializingRegions, AccountInitializingRegions)
			if err := r.statusUpdate(currentAcctInstance); err != nil {
				return err
			}
			return err
		}
	}
	go r.asyncRegionInit(reqLogger, currentAcctInstance, creds, regionAMIs, accountClaim.Spec.Aws.Regions)
	return nil
}