Skip to content

Commit 083f33a

Browse files
move AWS object to simple factory pattern
1 parent 0cb59aa commit 083f33a

File tree

8 files changed

+382
-391
lines changed

8 files changed

+382
-391
lines changed

cmd/account/cli.go

Lines changed: 20 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
11
package account
22

33
import (
4-
"context"
54
"fmt"
6-
"strings"
75

86
"github.com/aws/aws-sdk-go/aws"
9-
"github.com/aws/aws-sdk-go/service/sts"
10-
awsv1alpha1 "github.com/openshift/aws-account-operator/pkg/apis/aws/v1alpha1"
117
"github.com/spf13/cobra"
12-
corev1 "k8s.io/api/core/v1"
13-
"k8s.io/apimachinery/pkg/types"
148

159
"k8s.io/cli-runtime/pkg/genericclioptions"
16-
"k8s.io/klog"
1710
cmdutil "k8s.io/kubectl/pkg/cmd/util"
18-
"sigs.k8s.io/controller-runtime/pkg/client"
1911

20-
"github.com/openshift/osd-utils-cli/cmd/common"
21-
"github.com/openshift/osd-utils-cli/pkg/k8s"
12+
k8spkg "github.com/openshift/osd-utils-cli/pkg/k8s"
2213
awsprovider "github.com/openshift/osd-utils-cli/pkg/provider/aws"
2314
)
2415

@@ -36,62 +27,41 @@ func newCmdCli(streams genericclioptions.IOStreams, flags *genericclioptions.Con
3627
},
3728
}
3829

39-
cliCmd.Flags().StringVar(&ops.accountNamespace, "account-namespace", common.AWSAccountNamespace,
40-
"The namespace to keep AWS accounts. The default value is aws-account-operator.")
41-
cliCmd.Flags().StringVarP(&ops.accountName, "account-name", "a", "", "The AWS Account CR name to generate the credentials for")
42-
cliCmd.Flags().StringVarP(&ops.accountID, "account-id", "i", "", "The AWS Account ID we need to create temporary AWS credentials for -- This argument will not work for CCS accounts")
43-
cliCmd.Flags().StringVarP(&ops.clusterID, "cluster-id", "C", "", "The Internal Cluster ID from Hive to create AWS console URL for")
44-
cliCmd.Flags().StringVarP(&ops.profile, "aws-profile", "p", "", "specify AWS profile")
45-
cliCmd.Flags().StringVarP(&ops.cfgFile, "aws-config", "c", "", "specify AWS config file path")
46-
cliCmd.Flags().StringVarP(&ops.region, "aws-region", "r", common.DefaultRegion, "specify AWS region")
47-
cliCmd.Flags().Int64VarP(&ops.cliDuration, "duration", "d", 3600, "The duration of the cli token. "+
48-
"Default value is 3600 seconds(1 hour)")
30+
ops.k8sclusterresourcefactory.AttachCobraCliFlags(cliCmd)
31+
4932
cliCmd.Flags().BoolVarP(&ops.verbose, "verbose", "v", false, "Verbose output")
5033

5134
return cliCmd
5235
}
5336

5437
// cliOptions defines the struct for running the cli command
5538
type cliOptions struct {
56-
accountName string
57-
accountID string
58-
accountNamespace string
59-
clusterID string
60-
cliDuration int64
61-
62-
// AWS config
63-
region string
64-
profile string
65-
cfgFile string
39+
k8sclusterresourcefactory k8spkg.ClusterResourceFactoryOptions
6640

6741
verbose bool
6842

69-
flags *genericclioptions.ConfigFlags
7043
genericclioptions.IOStreams
71-
kubeCli client.Client
7244
}
7345

7446
func newCliOptions(streams genericclioptions.IOStreams, flags *genericclioptions.ConfigFlags) *cliOptions {
7547
return &cliOptions{
76-
flags: flags,
48+
k8sclusterresourcefactory: k8spkg.ClusterResourceFactoryOptions{
49+
Flags: flags,
50+
},
7751
IOStreams: streams,
7852
}
7953
}
8054

8155
func (o *cliOptions) complete(cmd *cobra.Command) error {
82-
// account CR name and account ID cannot be empty at the same time
83-
if o.accountName == "" && o.accountID == "" && o.clusterID == "" {
84-
return cmdutil.UsageErrorf(cmd, "AWS account CR name, AWS account ID and Cluster ID cannot be empty at the same time")
85-
}
86-
87-
if !o.hasOnlyOneTarget() {
88-
return cmdutil.UsageErrorf(cmd, "AWS account CR name, AWS account ID, or Cluster ID cannot be set at the same time")
56+
k8svalid, err := o.k8sclusterresourcefactory.ValidateIdentifiers()
57+
if !k8svalid {
58+
if err != nil {
59+
return err
60+
}
8961
}
9062

91-
// only initialize kubernetes client when account name or cluster ID is set
92-
if o.accountName != "" || o.clusterID != "" {
93-
var err error
94-
o.kubeCli, err = k8s.NewClient(o.flags)
63+
awsvalid, err := o.k8sclusterresourcefactory.Awscloudfactory.ValidateIdentifiers()
64+
if !awsvalid {
9565
if err != nil {
9666
return err
9767
}
@@ -100,118 +70,17 @@ func (o *cliOptions) complete(cmd *cobra.Command) error {
10070
return nil
10171
}
10272

103-
func (o *cliOptions) hasOnlyOneTarget() bool {
104-
targets := []string{o.accountName, o.accountID, o.clusterID}
105-
targetCount := 0
106-
for _, t := range targets {
107-
if t != "" {
108-
targetCount++
109-
}
110-
}
111-
return targetCount == 1
112-
}
113-
11473
func (o *cliOptions) run() error {
115-
var err error
116-
awsClient, err := awsprovider.NewAwsClient(o.profile, o.region, o.cfgFile)
117-
if err != nil {
118-
return err
119-
}
120-
121-
ctx := context.TODO()
122-
var accountID string
123-
if o.clusterID != "" {
124-
accountClaim, err := k8s.GetAccountClaimFromClusterID(ctx, o.kubeCli, o.clusterID)
125-
if err != nil {
126-
return err
127-
}
128-
if accountClaim == nil {
129-
return fmt.Errorf("Could not find any accountClaims for cluster with ID: %s", o.clusterID)
130-
}
131-
if accountClaim.Spec.AccountLink == "" {
132-
return fmt.Errorf("An unexpected error occured: the AccountClaim has no Account")
133-
}
134-
o.accountName = accountClaim.Spec.AccountLink
135-
}
136-
var isBYOC bool
137-
var acctSuffix string
138-
if o.accountName != "" {
139-
account, err := k8s.GetAWSAccount(ctx, o.kubeCli, o.accountNamespace, o.accountName)
140-
if err != nil {
141-
return err
142-
}
143-
accountID = account.Spec.AwsAccountID
144-
isBYOC = account.Spec.BYOC
145-
acctSuffix = account.Labels["iamUserId"]
146-
} else {
147-
accountID = o.accountID
148-
isBYOC = false
149-
}
150-
151-
callerIdentityOutput, err := awsClient.GetCallerIdentity(&sts.GetCallerIdentityInput{})
74+
awsClient, err := o.k8sclusterresourcefactory.GetCloudProvider(o.verbose)
15275
if err != nil {
153-
klog.Error("Fail to get caller identity. Could you please validate the credentials?")
15476
return err
15577
}
156-
if o.verbose {
157-
fmt.Fprintln(o.Out, callerIdentityOutput)
158-
}
159-
160-
splitArn := strings.Split(*callerIdentityOutput.Arn, "/")
161-
username := splitArn[1]
162-
sessionName := fmt.Sprintf("RH-SRE-%s", username)
163-
164-
// If BYOC we need to role-chain to use the right creds.
165-
// Use the OrgAccess Role by default, override if BYOC
166-
roleName := awsv1alpha1.AccountOperatorIAMRole
167-
168-
// TODO: Come back to this and do a lookup for the account CR if the account ID is the only one set so we can do this too.
169-
if isBYOC {
170-
cm := &corev1.ConfigMap{}
171-
err = o.kubeCli.Get(ctx, types.NamespacedName{Namespace: awsv1alpha1.AccountCrNamespace, Name: awsv1alpha1.DefaultConfigMap}, cm)
172-
if err != nil {
173-
klog.Error("There was an error getting the configmap.")
174-
return err
175-
}
176-
roleArn := cm.Data["CCS-Access-Arn"]
177-
178-
if roleArn == "" {
179-
klog.Error("Empty SRE Jump Role in ConfigMap")
180-
return fmt.Errorf("Empty ConfigMap Value")
181-
}
18278

183-
// Build the role-name for Access:
184-
if acctSuffix == "" {
185-
klog.Error("Unexpected error parsing the account CR suffix")
186-
return fmt.Errorf("Unexpected error parsing the account CR suffix.")
187-
}
188-
roleName = fmt.Sprintf("BYOCAdminAccess-%s", acctSuffix)
189-
190-
// Get STS Credentials
191-
if o.verbose {
192-
fmt.Printf("Elevating Access to SRE Jump Role for user %s\n", sessionName)
193-
}
194-
creds, err := awsprovider.GetAssumeRoleCredentials(awsClient, &o.cliDuration, aws.String(sessionName), aws.String(roleArn))
195-
if err != nil {
196-
klog.Error("Failed to get jump-role creds for CCS")
197-
return err
198-
}
199-
200-
awsClientInput := &awsprovider.AwsClientInput{
201-
AccessKeyID: *creds.AccessKeyId,
202-
SecretAccessKey: *creds.SecretAccessKey,
203-
SessionToken: *creds.SessionToken,
204-
Region: "us-east-1",
205-
}
206-
// New Client with STS Credentials
207-
awsClient, err = awsprovider.NewAwsClientWithInput(awsClientInput)
208-
if err != nil {
209-
klog.Error("Failed to assume jump-role for CCS")
210-
return err
211-
}
212-
}
213-
credentials, err := awsprovider.GetAssumeRoleCredentials(awsClient, &o.cliDuration,
214-
callerIdentityOutput.UserId, aws.String(fmt.Sprintf("arn:aws:iam::%s:role/%s", accountID, roleName)))
79+
credentials, err := awsprovider.GetAssumeRoleCredentials(awsClient, &o.k8sclusterresourcefactory.Awscloudfactory.ConsoleDuration,
80+
o.k8sclusterresourcefactory.Awscloudfactory.CallerIdentity.UserId,
81+
aws.String(fmt.Sprintf("arn:aws:iam::%s:role/%s",
82+
o.k8sclusterresourcefactory.AccountID,
83+
o.k8sclusterresourcefactory.Awscloudfactory.RoleName)))
21584
if err != nil {
21685
return err
21786
}

0 commit comments

Comments
 (0)