11package _import
22
33import (
4+ "encoding/json"
5+ "fmt"
6+ "os"
7+ "strings"
8+
9+ "github.com/IBM/go-sdk-core/v4/core"
10+ rcv2 "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
11+ "github.com/spf13/cobra"
12+ "k8s.io/klog/v2"
13+
414 "github.com/ppc64le-cloud/pvsadm/pkg"
515 "github.com/ppc64le-cloud/pvsadm/pkg/client"
616 "github.com/ppc64le-cloud/pvsadm/pkg/utils"
7- "github.com/spf13/cobra"
8- "k8s.io/klog/v2"
17+ )
918
10- "os"
11- "strings "
19+ const (
20+ ServiceCredName = "pvsadm-service-cred "
1221)
1322
1423var Cmd = & cobra.Command {
@@ -22,17 +31,21 @@ export IBMCLOUD_API_KEY=<IBM_CLOUD_API_KEY>
2231
2332Examples:
2433
25- # importing image from default region and using default storage type
34+ # importing image from default region and using default storage type (service credential will be autogenerated)
35+ pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --object-name rhel-83-10032020.ova.gz --image-name test-image
36+
37+ # importing image from default region and using default storage type with specifying the accesskey and secretkey explicitly
2638pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --accesskey <ACCESSKEY> --secretkey <SECRETKEY> --object-name rhel-83-10032020.ova.gz --image-name test-image
2739
2840# with user provided storage type and region
29- pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --accesskey <ACCESSKEY> --secretkey <SECRETKEY> - r <REGION> --storagetype <STORAGETYPE> --object-name rhel-83-10032020.ova.gz --image-name test-image
41+ pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> -r <REGION> --storagetype <STORAGETYPE> --object-name rhel-83-10032020.ova.gz --image-name test-image
3042
3143# If user wants to specify the type of OS
32- pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --accesskey <ACCESSKEY> --secretkey <SECRETKEY> -- object-name rhel-83-10032020.ova.gz --image-name test-image --ostype <OSTYPE>
44+ pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --object-name rhel-83-10032020.ova.gz --image-name test-image --ostype <OSTYPE>
3345` ,
3446 RunE : func (cmd * cobra.Command , args []string ) error {
3547 opt := pkg .ImageCMDOptions
48+ apikey := pkg .Options .APIKey
3649 //validate inputs
3750 validOsType := []string {"aix" , "ibmi" , "redhat" , "sles" }
3851 validStorageType := []string {"tier3" , "tier1" }
@@ -47,7 +60,89 @@ pvsadm image import -n upstream-core-lon04 -b <BUCKETNAME> --accesskey <ACCESSKE
4760 os .Exit (1 )
4861 }
4962
50- c , err := client .NewClient (pkg .Options .APIKey )
63+ if opt .AccessKey == "" || opt .SecretKey == "" {
64+ klog .Info ("Auto Generating the COS Service credential for importing the image" )
65+ auth , err := core .NewIamAuthenticator (apikey , "" , "" , "" , false , nil )
66+ if err != nil {
67+ return err
68+ }
69+
70+ bxCli , err := client .NewClient (apikey )
71+ if err != nil {
72+ return err
73+ }
74+
75+ resourceController , err := client .NewResourceControllerV2 (& rcv2.ResourceControllerV2Options {
76+ Authenticator : auth ,
77+ })
78+ if err != nil {
79+ return err
80+ }
81+
82+ instances , _ , err := resourceController .ResourceControllerV2 .ListResourceInstances (resourceController .ResourceControllerV2 .NewListResourceInstancesOptions ().SetType ("service_instance" ))
83+ if err != nil {
84+ return err
85+ }
86+
87+ // Step 1: Find where COS for the bucket
88+ cosOfBucket := func (resources []rcv2.ResourceInstance ) * rcv2.ResourceInstance {
89+ for _ , resource := range resources {
90+ if strings .Contains (* resource .Crn , "cloud-object-storage" ) {
91+ s3client , err := client .NewS3Client (bxCli , * resource .Name , opt .Region )
92+ if err != nil {
93+ continue
94+ }
95+ buckets , err := s3client .S3Session .ListBuckets (nil )
96+ if err != nil {
97+ continue
98+ }
99+ for _ , bucket := range buckets .Buckets {
100+ if * bucket .Name == opt .BucketName {
101+ return & resource
102+ }
103+ }
104+ }
105+ }
106+ return nil
107+ }(instances .Resources )
108+
109+ if cosOfBucket == nil {
110+ return fmt .Errorf ("failed to find the COS instance for the bucket mentioned: %s" , opt .BucketName )
111+ }
112+ klog .Infof ("%s bucket found in the %s[ID:%s] COS instance" , opt .BucketName , * cosOfBucket .Name , * cosOfBucket .ID )
113+
114+ // Step 2: Create the Service Credential in the found COS instance
115+ createResourceKeyOptions := & client.CreateResourceKeyOptions {
116+ CreateResourceKeyOptions : resourceController .ResourceControllerV2 .NewCreateResourceKeyOptions (ServiceCredName , * cosOfBucket .ID ),
117+ Parameters : map [string ]interface {}{"HMAC" : true },
118+ }
119+
120+ key , _ , err := resourceController .CreateResourceKey (createResourceKeyOptions )
121+ if err != nil {
122+ return err
123+ }
124+ defer resourceController .ResourceControllerV2 .DeleteResourceKey (& rcv2.DeleteResourceKeyOptions {ID : key .ID })
125+
126+ jsonString , err := json .Marshal (key .Credentials .GetProperty ("cos_hmac_keys" ))
127+ if err != nil {
128+ return err
129+ }
130+ h := struct {
131+ AccessKeyID string `json:"access_key_id"`
132+ SecretKeyID string `json:"secret_access_key"`
133+ }{}
134+ err = json .Unmarshal (jsonString , & h )
135+ if err != nil {
136+ klog .Errorf ("failed to unmarshal the access credentials from the auto generated service credential" )
137+ return err
138+ }
139+
140+ // Step 3: Assign the Access Key and Secret Key for further operation
141+ opt .AccessKey = h .AccessKeyID
142+ opt .SecretKey = h .SecretKeyID
143+ }
144+
145+ c , err := client .NewClient (apikey )
51146 if err != nil {
52147 return err
53148 }
@@ -73,15 +168,13 @@ func init() {
73168 Cmd .Flags ().StringVarP (& pkg .ImageCMDOptions .InstanceID , "instance-id" , "i" , "" , "Instance ID of the PowerVS instance" )
74169 Cmd .Flags ().StringVarP (& pkg .ImageCMDOptions .BucketName , "bucket" , "b" , "" , "Cloud Storage bucket name" )
75170 Cmd .Flags ().StringVarP (& pkg .ImageCMDOptions .Region , "region" , "r" , "" , "Cloud Storage Region" )
76- Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .AccessKey , "accesskey" , "" , "Cloud Storage access key; required for import image " )
77- Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .SecretKey , "secretkey" , "" , "Cloud Storage secret key; required for import image " )
171+ Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .AccessKey , "accesskey" , "" , "Cloud Storage access key" )
172+ Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .SecretKey , "secretkey" , "" , "Cloud Storage secret key" )
78173 Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .ImageName , "image-name" , "" , "Name to give imported image" )
79174 Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .ImageFilename , "object-name" , "" , "Cloud Storage image filename" )
80- Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .OsType , "ostype" , "" , "Image OS Type, accepted values are[aix, ibmi, redhat, sles]" )
175+ Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .OsType , "ostype" , "redhat " , "Image OS Type, accepted values are[aix, ibmi, redhat, sles]" )
81176 Cmd .Flags ().StringVar (& pkg .ImageCMDOptions .StorageType , "storagetype" , "tier3" , "Storage type, accepted values are [tier1, tier3]" )
82177 _ = Cmd .MarkFlagRequired ("bucket" )
83- _ = Cmd .MarkFlagRequired ("accesskey" )
84- _ = Cmd .MarkFlagRequired ("secretkey" )
85178 _ = Cmd .MarkFlagRequired ("image-name" )
86179 _ = Cmd .MarkFlagRequired ("object-name" )
87180 _ = Cmd .MarkFlagRequired ("region" )
0 commit comments