forked from openshift/cloud-credential-operator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
create_service_id.go
169 lines (139 loc) · 5.38 KB
/
create_service_id.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package ibmcloud
import (
"fmt"
"log"
"os"
"path/filepath"
"github.com/openshift/cloud-credential-operator/pkg/cmd/provisioning"
"github.com/openshift/cloud-credential-operator/pkg/ibmcloud"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
// APIKeyEnvVars is a list of environment variable names containing an IBM Cloud API key
var APIKeyEnvVars = []string{"IC_API_KEY", "IBMCLOUD_API_KEY", "BM_API_KEY", "BLUEMIX_API_KEY"}
var (
// Options captures the options that affect creation/deletion of the generated
// objects.
Options = options{
TargetDir: "",
}
// APIKeyName is the name for the autogenerated API Key for the Service ID
APIKeyName = "ccoctl-generated-key"
)
// getEnv reads the content from first found environment variable from the envs list, returns empty string if none found.
func getEnv(envs []string) string {
for _, k := range envs {
if v := os.Getenv(k); v != "" {
return v
}
}
return ""
}
// NewCreateServiceIDCmd provides the "create-service-id" subcommand
func NewCreateServiceIDCmd() *cobra.Command {
createServiceIDCmd := &cobra.Command{
Use: "create-service-id",
Short: "Create Service ID",
RunE: createServiceIDCmd,
PersistentPreRun: initEnvForCreateServiceIDCmd,
}
createServiceIDCmd.PersistentFlags().StringVar(&Options.Name, "name", "", "User-defined name for all created IBM Cloud resources (can be separate from the cluster's infra-id)")
createServiceIDCmd.MarkPersistentFlagRequired("name")
createServiceIDCmd.PersistentFlags().StringVar(&Options.CredRequestDir, "credentials-requests-dir", "", "Directory containing files of CredentialsRequests to create IAM Roles for (can be created by running 'oc adm release extract --credentials-requests --cloud=ibmcloud' against an OpenShift release image)")
createServiceIDCmd.MarkPersistentFlagRequired("credentials-requests-dir")
createServiceIDCmd.PersistentFlags().StringVar(&Options.ResourceGroupName, "resource-group-name", "", "Name of the resource group used for scoping the access policies")
createServiceIDCmd.PersistentFlags().StringVar(&Options.TargetDir, "output-dir", "", "Directory to place generated files (defaults to current directory)")
createServiceIDCmd.PersistentFlags().BoolVar(&Options.EnableTechPreview, "enable-tech-preview", false, "Opt into processing CredentialsRequests marked as tech-preview")
return createServiceIDCmd
}
func createServiceIDCmd(cmd *cobra.Command, args []string) error {
apiKey := getEnv(APIKeyEnvVars)
if apiKey == "" {
return fmt.Errorf("%s environment variable not set", APIKeyEnvVars)
}
params := &ibmcloud.ClientParams{
InfraName: Options.Name,
}
ibmclient, err := ibmcloud.NewClient(apiKey, params)
if err != nil {
return err
}
apiKeyDetailsOptions := ibmclient.NewGetAPIKeysDetailsOptions()
apiKeyDetailsOptions.SetIamAPIKey(apiKey)
apiKeyDetails, _, err := ibmclient.GetAPIKeysDetails(apiKeyDetailsOptions)
if err != nil {
return errors.Wrap(err, "Failed to get Details for the given APIKey")
}
err = createServiceIDs(ibmclient, apiKeyDetails.AccountID, Options.Name, Options.ResourceGroupName,
Options.CredRequestDir, Options.TargetDir, Options.EnableTechPreview)
if err != nil {
return err
}
return nil
}
func createServiceIDs(client ibmcloud.Client, accountID *string,
name, resourceGroupName, credReqDir, targetDir string, enableTechPreview bool) error {
resourceGroupID, err := getResourceGroupID(client, accountID, resourceGroupName)
if err != nil {
return errors.Wrap(err, "Failed to getResourceGroupID")
}
// Process directory
credReqs, err := provisioning.GetListOfCredentialsRequests(credReqDir, enableTechPreview)
if err != nil {
return errors.Wrap(err, "Failed to process files containing CredentialsRequests")
}
var serviceIDs []*ServiceID
undo := func() {
for _, serviceID := range serviceIDs {
serviceID.UnDo(targetDir)
}
}
for _, cr := range credReqs {
serviceID := NewServiceID(client, name, *accountID, resourceGroupID, cr)
serviceIDs = append(serviceIDs, serviceID)
}
for _, serviceID := range serviceIDs {
if err := serviceID.Validate(); err != nil {
return errors.Wrap(err, "Failed to validate the serviceID")
}
}
for _, serviceID := range serviceIDs {
if err := serviceID.Do(); err != nil {
undo()
return errors.Wrap(err, "Failed to process the serviceID")
}
}
for _, serviceID := range serviceIDs {
if err := serviceID.Dump(targetDir); err != nil {
undo()
return errors.Wrap(err, "Failed to generate the secrets for serviceIDs")
}
}
return nil
}
// initEnvForCreateServiceIDCmd will ensure the destination directory is ready to receive the generated
// files, and will create the directory if necessary.
func initEnvForCreateServiceIDCmd(cmd *cobra.Command, args []string) {
if Options.TargetDir == "" {
pwd, err := os.Getwd()
if err != nil {
log.Fatalf("Failed to get current directory: %s", err)
}
Options.TargetDir = pwd
}
fPath, err := filepath.Abs(Options.TargetDir)
if err != nil {
log.Fatalf("Failed to resolve full path: %s", err)
}
// create target dir if necessary
err = provisioning.EnsureDir(fPath)
if err != nil {
log.Fatalf("failed to create target directory at %s", fPath)
}
// create manifests dir if necessary
manifestsDir := filepath.Join(fPath, manifestsDirName)
err = provisioning.EnsureDir(manifestsDir)
if err != nil {
log.Fatalf("failed to create manifests directory at %s", manifestsDir)
}
}