Skip to content

Commit 3b810d2

Browse files
author
Power Cloud Robot
authored
Merge pull request #612 from kishen-v/deprecate-bluemix
Deprecate bluemix-go and clean-up code.
2 parents 05b0282 + 5001afd commit 3b810d2

File tree

20 files changed

+480
-601
lines changed

20 files changed

+480
-601
lines changed

cmd/dhcp-sync/dhcp-sync.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func syncDHCPD() {
8787
klog.Fatalf("failed to create a session with IBM cloud: %v", err)
8888
}
8989

90-
pvmclient, err := client.NewPVMClientWithEnv(c, pkg.Options.WorkspaceID, "", "prod")
90+
pvmclient, err := client.NewPVMClientWithEnv(c, pkg.Options.WorkspaceID, "", client.DefaultEnvProd)
9191
if err != nil {
9292
klog.Fatalf("failed to create a PVM client: %v", err)
9393
}
@@ -162,9 +162,6 @@ var Cmd = &cobra.Command{
162162
if pkg.Options.WorkspaceID == "" {
163163
return fmt.Errorf("--workspace-id is required")
164164
}
165-
if pkg.Options.APIKey == "" {
166-
return fmt.Errorf("api-key can't be empty, pass the token via --api-key or set IBMCLOUD_API_KEY environment variable")
167-
}
168165
return nil
169166
},
170167
RunE: func(cmd *cobra.Command, args []string) error {

cmd/dhcpserver/cmd.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ var Cmd = &cobra.Command{
2727
Short: "dhcpserver command",
2828
GroupID: "dhcp",
2929
PreRunE: func(cmd *cobra.Command, args []string) error {
30-
if pkg.Options.APIKey == "" {
31-
return fmt.Errorf("api-key can't be empty, pass the token via --api-key or set IBMCLOUD_API_KEY environment variable")
32-
}
3330
if pkg.Options.WorkspaceID == "" {
3431
return fmt.Errorf("--workspace-id required")
3532
}

cmd/get/cloudconnections/cloudconnections.go

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package cloudconnections
1616

1717
import (
18-
"os"
1918
"strings"
2019

2120
"github.com/IBM-Cloud/power-go-client/ibmpisession"
@@ -46,13 +45,6 @@ var Cmd = &cobra.Command{
4645
Use: "cloud-connections",
4746
Short: "List the existing cloud connections in the account",
4847
Long: "List the existing cloud connections enabled across all workspaces in the account",
49-
PreRunE: func(md *cobra.Command, args []string) error {
50-
opt := pkg.Options
51-
// TODO: The GetAuthenticatorFromEnvironment function seems to refer to "IBMCLOUD_APIKEY" rather than IBMCLOUD_API_KEY as used in the project.
52-
// In order to use the resourcecontrollerv2's functionality, the IBMCLOUD_API_KEY is re-exported as IBMCLOUD_APIKEY.
53-
os.Setenv("IBMCLOUD_APIKEY", opt.APIKey)
54-
return nil
55-
},
5648
RunE: func(cmd *cobra.Command, args []string) error {
5749
opt := pkg.Options
5850
c, err := client.NewClientWithEnv(opt.APIKey, opt.Environment, opt.Debug)
@@ -61,6 +53,10 @@ var Cmd = &cobra.Command{
6153
return err
6254
}
6355

56+
environment, err := client.GetEnvironment(opt.Environment)
57+
if err != nil {
58+
return err
59+
}
6460
// Retrieve all workspaces that are available in the account.
6561
workspaceInstances, err := c.ListWorkspaceInstances()
6662
if err != nil {
@@ -73,18 +69,24 @@ var Cmd = &cobra.Command{
7369
zoneWorkspaces[*workspaceInstance.RegionID] = append(zoneWorkspaces[*workspaceInstance.RegionID], workspaceDetails{name: *workspaceInstance.Name, guid: *workspaceInstance.GUID})
7470
}
7571
cloudConnections := map[string]cloudConnectionDetails{}
76-
authenticator := &core.IamAuthenticator{ApiKey: c.Config.BluemixAPIKey, URL: *c.Config.TokenProviderEndpoint}
72+
authenticator := &core.IamAuthenticator{ApiKey: pkg.Options.APIKey, URL: environment[client.TPEndpoint]}
7773
klog.Info("Listing cloud connections across all workspaces, please wait..")
7874
// Create a IBM PI Session per zone and reuse them across the workspaces in the same zone.
7975
for workspaceZone, workspaces := range zoneWorkspaces {
80-
pvmclientOptions := ibmpisession.IBMPIOptions{Authenticator: authenticator, Debug: pkg.Options.Debug, UserAccount: c.User.Account, Zone: workspaceZone}
76+
pvmclientOptions := ibmpisession.IBMPIOptions{
77+
Authenticator: authenticator,
78+
Debug: pkg.Options.Debug,
79+
URL: environment[client.PIEndpoint],
80+
UserAccount: c.User.Account,
81+
Zone: workspaceZone,
82+
}
8183
piSession, err := ibmpisession.NewIBMPISession(&pvmclientOptions)
8284
if err != nil {
8385
return err
8486
}
8587
// Iterate over the workspaces available in the zone.
8688
for _, workspace := range workspaces {
87-
pvmClient, err := client.NewGenericPVMClientWithEnv(c, workspace.guid, workspace.name, opt.Environment, piSession)
89+
pvmClient, err := client.NewGenericPVMClient(c, workspace.guid, piSession)
8890
if err != nil {
8991
return err
9092
}
@@ -130,8 +132,4 @@ var Cmd = &cobra.Command{
130132
klog.Info("There are no active cloud connections in this account.")
131133
return nil
132134
},
133-
PostRunE: func(md *cobra.Command, args []string) error {
134-
os.Unsetenv("IBMCLOUD_APIKEY")
135-
return nil
136-
},
137135
}

cmd/image/import/import.go

Lines changed: 118 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -19,46 +19,69 @@ import (
1919
"strings"
2020
"time"
2121

22-
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/controller"
23-
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
24-
"github.com/IBM-Cloud/bluemix-go/crn"
25-
"github.com/IBM-Cloud/bluemix-go/models"
2622
pmodels "github.com/IBM-Cloud/power-go-client/power/models"
23+
"github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
2724
"github.com/spf13/cobra"
2825
"k8s.io/klog/v2"
26+
"k8s.io/utils/ptr"
2927

3028
"github.com/ppc64le-cloud/pvsadm/pkg"
3129
"github.com/ppc64le-cloud/pvsadm/pkg/client"
3230
"github.com/ppc64le-cloud/pvsadm/pkg/utils"
3331
)
3432

3533
const (
34+
accessKeyId = "access_key_id"
35+
cosHmacKeys = "cos_hmac_keys"
36+
crnServiceRoleWriter = "crn:v1:bluemix:public:iam::::serviceRole:Writer"
37+
imageStateActive = "active"
38+
jobStateCompleted = "completed"
39+
jobStateFailed = "failed"
40+
secretAccessKey = "secret_access_key"
41+
// CosResourceID is IBM COS service id, can be retrieved using ibmcloud cli
42+
// ibmcloud catalog service cloud-object-storage.
3643
serviceCredPrefix = "pvsadm-service-cred"
37-
imageStateActive = "active"
38-
jobStateCompleted = "completed"
39-
jobStateFailed = "failed"
4044
)
4145

42-
// Find COSINSTANCE details of the Provided bucket
43-
func findCOSInstanceDetails(resources []models.ServiceInstanceV2, bxCli *client.Client) (string, string, crn.CRN) {
46+
// findCOSInstance retrieves the service instance in which the bucket is present.
47+
func findCOSInstanceDetails(resources []resourcecontrollerv2.ResourceInstance, pvsClient *client.Client) *resourcecontrollerv2.ResourceInstance {
4448
for _, resource := range resources {
45-
if resource.Crn.ServiceName == "cloud-object-storage" {
46-
s3client, err := client.NewS3Client(bxCli, resource.Name, pkg.ImageCMDOptions.Region)
47-
if err != nil {
48-
continue
49-
}
50-
buckets, err := s3client.S3Session.ListBuckets(nil)
51-
if err != nil {
52-
continue
53-
}
54-
for _, bucket := range buckets.Buckets {
55-
if *bucket.Name == pkg.ImageCMDOptions.BucketName {
56-
return resource.Name, resource.Guid, resource.Crn
57-
}
49+
s3client, err := client.NewS3Client(pvsClient, *resource.Name, pkg.ImageCMDOptions.Region)
50+
if err != nil {
51+
klog.Warningf("cannot create a new s3 client. err: %v", err)
52+
continue
53+
}
54+
buckets, err := s3client.S3Session.ListBuckets(nil)
55+
if err != nil {
56+
klog.Warningf("cannot list buckets in the resource instance. err: %v", err)
57+
continue
58+
}
59+
for _, bucket := range buckets.Buckets {
60+
if *bucket.Name == pkg.ImageCMDOptions.BucketName {
61+
return &resource
5862
}
5963
}
6064
}
61-
return "", "", crn.CRN{}
65+
return nil
66+
}
67+
68+
// createNewCredentialsWithHMAC generates the service credentials in the given COS instance with HMAC keys.
69+
func createNewCredentialsWithHMAC(pvsClient *client.Client, cosCRN, serviceCredName string) (*resourcecontrollerv2.ResourceKey, error) {
70+
klog.V(2).Infof("Auto generating COS service credentials to import image: %s", serviceCredName)
71+
params := &resourcecontrollerv2.ResourceKeyPostParameters{}
72+
params.SetProperty("HMAC", true)
73+
key, _, err := pvsClient.ResourceControllerClient.CreateResourceKey(
74+
&resourcecontrollerv2.CreateResourceKeyOptions{
75+
Name: ptr.To(serviceCredName),
76+
Parameters: params,
77+
Role: ptr.To(crnServiceRoleWriter),
78+
Source: ptr.To(cosCRN),
79+
},
80+
)
81+
if err != nil {
82+
return nil, fmt.Errorf("unable to create resource key for service instance: %v", err.Error())
83+
}
84+
return key, nil
6285
}
6386

6487
// checkStorageTierAvailability confirms if the provided cloud instance ID supports the required storageType.
@@ -95,9 +118,9 @@ pvsadm image import --help for information
95118
# Set the API key or feed the --api-key commandline argument
96119
export IBMCLOUD_API_KEY=<IBM_CLOUD_API_KEY>
97120
98-
# To Import the image across the two different IBM account use accesskey and secretkey options
121+
# To Import the image across the two different IBM account use "--accesskey" and "--secretkey" options
99122
100-
# To Import the image from public bucket use public-bucket option
123+
# To Import the image from public bucket use the "--public-bucket" or "-p" option
101124
102125
Examples:
103126
@@ -132,12 +155,12 @@ pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --object rhel-83-1003
132155
opt := pkg.ImageCMDOptions
133156
apikey := pkg.Options.APIKey
134157

135-
bxCli, err := client.NewClientWithEnv(apikey, pkg.Options.Environment, pkg.Options.Debug)
158+
pvsClient, err := client.NewClientWithEnv(apikey, pkg.Options.Environment, pkg.Options.Debug)
136159
if err != nil {
137160
return err
138161
}
139162

140-
pvmclient, err := client.NewPVMClientWithEnv(bxCli, opt.WorkspaceID, opt.WorkspaceName, pkg.Options.Environment)
163+
pvmclient, err := client.NewPVMClientWithEnv(pvsClient, opt.WorkspaceID, opt.WorkspaceName, pkg.Options.Environment)
141164
if err != nil {
142165
return err
143166
}
@@ -148,54 +171,87 @@ pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --object rhel-83-1003
148171

149172
//Create AccessKey and SecretKey for the bucket provided if bucket access is private
150173
if (opt.AccessKey == "" || opt.SecretKey == "") && (!opt.Public) {
151-
//Find CosInstance of the bucket
152-
var svcs []models.ServiceInstanceV2
153-
svcs, err = bxCli.ResourceClientV2.ListInstances(controllerv2.ServiceInstanceQuery{
154-
Type: "service_instance",
155-
})
174+
// Find COS instance of the bucket
175+
listServiceInstanceOptions := &resourcecontrollerv2.ListResourceInstancesOptions{
176+
ResourceID: ptr.To(utils.CosResourceID),
177+
}
178+
179+
workspaces, _, err := pvsClient.ResourceControllerClient.ListResourceInstances(listServiceInstanceOptions)
156180
if err != nil {
157-
return err
181+
return fmt.Errorf("failed to list the resource instances: %v", err)
158182
}
159-
cosInstanceName, cosID, crn := findCOSInstanceDetails(svcs, bxCli)
160-
if cosInstanceName == "" {
183+
if len(workspaces.Resources) == 0 {
184+
return fmt.Errorf("no service instances were found")
185+
}
186+
187+
cosInstance := findCOSInstanceDetails(workspaces.Resources, pvsClient)
188+
if cosInstance == nil {
161189
return fmt.Errorf("failed to find the COS instance for the bucket mentioned: %s", opt.BucketName)
162190
}
163191

164-
keys, err := bxCli.GetResourceKeys(cosID)
192+
klog.Infof("Identified bucket %q in service instance: %s", opt.BucketName, *cosInstance.Name)
193+
listResourceKeysInstanceOptions := &resourcecontrollerv2.ListResourceKeysForInstanceOptions{
194+
ID: cosInstance.GUID,
195+
}
196+
keys, _, err := pvsClient.ResourceControllerClient.ListResourceKeysForInstance(listResourceKeysInstanceOptions)
165197
if err != nil {
166-
return fmt.Errorf("failed to list the service credentials: %v", err)
198+
return fmt.Errorf("cannot list the resource keys for instance. err: %v", err)
167199
}
168200

169-
var cred map[string]interface{}
170-
var ok bool
171-
if len(keys) == 0 {
172-
if opt.ServiceCredName == "" {
173-
opt.ServiceCredName = serviceCredPrefix + "-" + cosInstanceName
174-
}
201+
var ok, credentialsPresent bool
202+
var hmacKeys map[string]interface{}
203+
var key *resourcecontrollerv2.ResourceKey
175204

176-
// Create the service credential if does not exist
177-
klog.V(2).Infof("Auto Generating the COS Service credential for importing the image with name: %s", opt.ServiceCredName)
178-
CreateServiceKeyRequest := controller.CreateServiceKeyRequest{
179-
Name: opt.ServiceCredName,
180-
SourceCRN: crn,
181-
Parameters: map[string]interface{}{"HMAC": true},
182-
}
183-
newKey, err := bxCli.ResourceServiceKey.CreateKey(CreateServiceKeyRequest)
184-
if err != nil {
185-
return err
205+
if opt.ServiceCredName == "" {
206+
opt.ServiceCredName = serviceCredPrefix + "-" + *cosInstance.Name
207+
}
208+
209+
// Create the service credential if does not exist
210+
if len(keys.Resources) == 0 {
211+
if key, err = createNewCredentialsWithHMAC(pvsClient, *cosInstance.CRN, opt.ServiceCredName); err != nil {
212+
return fmt.Errorf("error while creating HMAC credentials. err: %v", err)
186213
}
187-
cred, ok = newKey.Credentials["cos_hmac_keys"].(map[string]interface{})
188214
} else {
189-
// Use the service credential already created
190215
klog.V(2).Info("Reading the existing service credential")
191-
cred, ok = keys[0].Credentials["cos_hmac_keys"].(map[string]interface{})
216+
// Use the service credential already created. There may be a possibility that multiple credentials exist, but the HMAC credentials may not be present.
217+
// In such case, manually re-create the credentials.
218+
219+
for _, serviceCredential := range keys.Resources {
220+
key, _, err = pvsClient.ResourceControllerClient.GetResourceKey(
221+
&resourcecontrollerv2.GetResourceKeyOptions{
222+
ID: serviceCredential.ID,
223+
},
224+
)
225+
if err != nil {
226+
return fmt.Errorf("an error occured while retriving the resource key. err: %v", err)
227+
}
228+
// if the current credential has COS HMAC keys, reuse the same for importing the image
229+
if prop := key.Credentials.GetProperty(cosHmacKeys); prop != nil {
230+
klog.Infof("HMAC keys are available from the credential %q, re-using the same for image upload", *key.Name)
231+
credentialsPresent = true
232+
break
233+
}
234+
klog.Infof("No credentials found in the key %q.", *key.Name)
235+
}
236+
// if all the available service credentials do not have HMAC, create one with HMAC.
237+
if !credentialsPresent {
238+
if key, err = createNewCredentialsWithHMAC(pvsClient, *cosInstance.CRN, opt.ServiceCredName); err != nil {
239+
return fmt.Errorf("error while creating HMAC credentials. err: %v", err)
240+
}
241+
}
192242
}
193-
if !ok {
194-
return fmt.Errorf("failed to get the accessKey and secretKey from service credential")
243+
244+
prop := key.Credentials.GetProperty(cosHmacKeys)
245+
if prop == nil {
246+
return fmt.Errorf("unable to retrieve COS HMAC keys")
247+
}
248+
249+
if hmacKeys, ok = prop.(map[string]interface{}); !ok {
250+
return fmt.Errorf("type assertion for HMAC keys failed")
195251
}
196-
//Assign the Access Key and Secret Key for further operation
197-
opt.AccessKey = cred["access_key_id"].(string)
198-
opt.SecretKey = cred["secret_access_key"].(string)
252+
// Assign the Access Key and Secret Key for further operation
253+
opt.AccessKey = hmacKeys[accessKeyId].(string)
254+
opt.SecretKey = hmacKeys[secretAccessKey].(string)
199255
}
200256

201257
//By default Bucket Access is private
@@ -231,7 +287,7 @@ pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --object rhel-83-1003
231287
}
232288

233289
var image *pmodels.ImageReference = &pmodels.ImageReference{}
234-
klog.V(1).Info("Retrieving image details")
290+
klog.Info("Retrieving image details")
235291

236292
if image.ImageID == nil {
237293
image, err = pvmclient.ImgClient.GetImageByName(opt.ImageName)

cmd/image/sync/sync.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ type InstanceItem struct {
4343

4444
// sync constants
4545
const (
46-
serviceType = "cloud-object-storage"
47-
maxWorkers = 20
46+
maxWorkers = 20
4847
)
4948

5049
// Worker method to copy object from source bucket to target bucket
@@ -64,18 +63,18 @@ func copyWorker(copyJobs <-chan copyWorkload, results chan<- bool, workerId int)
6463
}
6564

6665
// Method to create the list of required instances
67-
func createInstanceList(spec []pkg.Spec, bxCli *client.Client) ([]InstanceItem, error) {
66+
func createInstanceList(spec []pkg.Spec, client *client.Client) ([]InstanceItem, error) {
6867
var instanceList []InstanceItem
6968
for _, item := range spec {
7069
instance := InstanceItem{}
71-
s3Cli, err := NewS3Client(bxCli, item.Source.Cos, item.Source.Region)
70+
s3Cli, err := NewS3Client(client, item.Source.Cos, item.Source.Region)
7271
if err != nil {
7372
return nil, err
7473
}
7574

7675
instance.Source = s3Cli
7776
for _, targetItem := range item.Target {
78-
s3Cli, err := NewS3Client(bxCli, item.Source.Cos, targetItem.Region)
77+
s3Cli, err := NewS3Client(client, item.Source.Cos, targetItem.Region)
7978
if err != nil {
8079
return nil, err
8180
}
@@ -257,7 +256,7 @@ Sample spec.yaml file:
257256
start := time.Now()
258257

259258
//Create bluemix client
260-
bxCli, err := client.NewClientWithEnv(apikey, pkg.Options.Environment, pkg.Options.Debug)
259+
pvsClient, err := client.NewClientWithEnv(apikey, pkg.Options.Environment, pkg.Options.Debug)
261260
if err != nil {
262261
return err
263262
}
@@ -269,7 +268,7 @@ Sample spec.yaml file:
269268
}
270269

271270
// Create necessary objects
272-
instanceList, err := createInstanceList(spec, bxCli)
271+
instanceList, err := createInstanceList(spec, pvsClient)
273272
if err != nil {
274273
return err
275274
}

0 commit comments

Comments
 (0)