@@ -15,6 +15,7 @@ import (
15
15
"k8s.io/apimachinery/pkg/api/errors"
16
16
17
17
corev1 "k8s.io/api/core/v1"
18
+ "k8s.io/klog/v2"
18
19
19
20
"github.com/IBM/go-sdk-core/v5/core"
20
21
"github.com/IBM/ibm-cos-sdk-go/aws"
@@ -40,7 +41,12 @@ import (
40
41
)
41
42
42
43
const (
43
- IAMEndpoint = "https://iam.cloud.ibm.com/identity/token"
44
+ // IBMTokenPath is the URI path for the token endpoint
45
+ IAMTokenPath = "/identity/token"
46
+ // IAMEndpoint is the default IAM token endpoint
47
+ IAMEndpoint = "https://iam.cloud.ibm.com/identity/token"
48
+
49
+ cosEndpointTemplate = "s3.%s.cloud-object-storage.appdomain.cloud"
44
50
imageRegistrySecretDataKey = "credentials"
45
51
imageRegistrySecretMountpoint = "/var/run/secrets/cloud"
46
52
)
@@ -57,6 +63,12 @@ type driver struct {
57
63
// IBM Services used only during tests.
58
64
resourceController * resourcecontrollerv2.ResourceControllerV2
59
65
resourceManager * resourcemanagerv2.ResourceManagerV2
66
+
67
+ // Endpoints to use for IBM Cloud Services
68
+ iamServiceEndpoint string
69
+ cosServiceEndpoint string
70
+ rcServiceEndpoint string
71
+ rmServiceEndpoint string
60
72
}
61
73
62
74
// NewDriver creates a new IBM COS storage driver.
@@ -81,12 +93,18 @@ func (d *driver) ConfigEnv() (envs envvar.List, err error) {
81
93
if err != nil {
82
94
return
83
95
}
96
+ // Build the regional COS endpoint, or use the override endpoint if one was provided
97
+ regionEndpoint := fmt .Sprintf (cosEndpointTemplate , d .Config .Location )
98
+ if d .cosServiceEndpoint != "" {
99
+ // We expect the override already is region specific
100
+ regionEndpoint = d .cosServiceEndpoint
101
+ }
84
102
85
103
envs = append (envs ,
86
104
envvar.EnvVar {Name : "REGISTRY_STORAGE" , Value : "s3" },
87
105
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_BUCKET" , Value : d .Config .Bucket },
88
106
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_REGION" , Value : d .Config .Location },
89
- envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_REGIONENDPOINT" , Value : fmt . Sprintf ( "s3.%s.cloud-object-storage.appdomain.cloud" , d . Config . Location ) },
107
+ envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_REGIONENDPOINT" , Value : regionEndpoint },
90
108
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_ENCRYPT" , Value : false },
91
109
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_VIRTUALHOSTEDSTYLE" , Value : false },
92
110
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_USEDUALSTACK" , Value : false },
@@ -122,6 +140,7 @@ func (d *driver) UpdateEffectiveConfig() (*imageregistryv1.ImageRegistryConfigSt
122
140
}
123
141
}
124
142
}
143
+ d .setServiceEndpointOverrides (infra )
125
144
126
145
// Use cluster defaults when custom config doesn't define values
127
146
if d .Config == nil || (len (effectiveConfig .Location ) == 0 ) {
@@ -163,7 +182,7 @@ func (d *driver) CreateStorage(cr *imageregistryv1.Config) error {
163
182
}
164
183
165
184
// Get resource controller service
166
- rc , err := d .getResouceControllerService ()
185
+ rc , err := d .getResourceControllerService ()
167
186
if err != nil {
168
187
return err
169
188
}
@@ -237,7 +256,10 @@ func (d *driver) CreateStorage(cr *imageregistryv1.Config) error {
237
256
},
238
257
)
239
258
if resourceGroups == nil || err != nil {
240
- return fmt .Errorf ("unable to get resource groups: %s with resp code: %d" , err .Error (), resp .StatusCode )
259
+ if resp != nil {
260
+ return fmt .Errorf ("unable to get resource groups: %s with resp code: %d" , err .Error (), resp .StatusCode )
261
+ }
262
+ return fmt .Errorf ("unable to get resource groups: %w using ResourceManager endpoint: %s" , err , rm .GetServiceURL ())
241
263
} else if len (resourceGroups .Resources ) == 0 {
242
264
return fmt .Errorf ("unable to find any resource groups with resp code: %d" , resp .StatusCode )
243
265
}
@@ -444,6 +466,35 @@ func (d *driver) CreateStorage(cr *imageregistryv1.Config) error {
444
466
return nil
445
467
}
446
468
469
+ // setServiceEndpointOverrides will collect any necessary IBM Cloud Service endpoint overrides and set them for the driver to use for IBM Cloud Services
470
+ func (d * driver ) setServiceEndpointOverrides (infra * configapiv1.Infrastructure ) {
471
+ // We currently only handle overrides for IBMCloud (api/config/v1/IBMCloudPlatformType), not PowerVS
472
+ if infra .Status .PlatformStatus != nil && infra .Status .PlatformStatus .Type == configapiv1 .IBMCloudPlatformType && infra .Status .PlatformStatus .IBMCloud != nil {
473
+ if len (infra .Status .PlatformStatus .IBMCloud .ServiceEndpoints ) > 0 {
474
+ for _ , endpoint := range infra .Status .PlatformStatus .IBMCloud .ServiceEndpoints {
475
+ switch endpoint .Name {
476
+ case configapiv1 .IBMCloudServiceCOS :
477
+ klog .Infof ("found override for ibmcloud cos endpoint: %s" , endpoint .URL )
478
+ d .cosServiceEndpoint = endpoint .URL
479
+ case configapiv1 .IBMCloudServiceIAM :
480
+ klog .Infof ("found override for ibmcloud iam endpoint: %s" , endpoint .URL )
481
+ d .iamServiceEndpoint = endpoint .URL
482
+ case configapiv1 .IBMCloudServiceResourceController :
483
+ klog .Infof ("found override for ibmcloud resource controller endpoint: %s" , endpoint .URL )
484
+ d .rcServiceEndpoint = endpoint .URL
485
+ case configapiv1 .IBMCloudServiceResourceManager :
486
+ klog .Infof ("found override for ibmcloud resource manager endpoint: %s" , endpoint .URL )
487
+ d .rmServiceEndpoint = endpoint .URL
488
+ case configapiv1 .IBMCloudServiceCIS , configapiv1 .IBMCloudServiceDNSServices , configapiv1 .IBMCloudServiceGlobalSearch , configapiv1 .IBMCloudServiceGlobalTagging , configapiv1 .IBMCloudServiceHyperProtect , configapiv1 .IBMCloudServiceKeyProtect , configapiv1 .IBMCloudServiceVPC :
489
+ klog .Infof ("ignoring unused service endpoint: %s" , endpoint .Name )
490
+ default :
491
+ klog .Infof ("ignoring unknown service: %s" , endpoint .Name )
492
+ }
493
+ }
494
+ }
495
+ }
496
+ }
497
+
447
498
// getAccountID returns the IBM Cloud account ID associated with the
448
499
// IAM API key.
449
500
func (d * driver ) getAccountID () (string , error ) {
@@ -456,6 +507,10 @@ func (d *driver) getAccountID() (string, error) {
456
507
ApiKey : IAMAPIKey ,
457
508
}
458
509
510
+ if d .iamServiceEndpoint != "" {
511
+ iamAuthenticator .URL = d .iamServiceEndpoint
512
+ }
513
+
459
514
// Get IAM token
460
515
iamToken , err := iamAuthenticator .RequestToken ()
461
516
if err != nil {
@@ -480,51 +535,81 @@ func (d *driver) getAccountID() (string, error) {
480
535
return accountID , nil
481
536
}
482
537
483
- // getResouceControllerService returns the IBM Cloud resource controller
484
- // client.
485
- func (d * driver ) getResouceControllerService () (* resourcecontrollerv2.ResourceControllerV2 , error ) {
538
+ // getResourceControllerService returns the IBM Cloud resource controller client.
539
+ func (d * driver ) getResourceControllerService () (* resourcecontrollerv2.ResourceControllerV2 , error ) {
486
540
if d .resourceController != nil {
487
541
return d .resourceController , nil
488
542
}
489
543
544
+ // Fetch the latest Infrastructure Status, for any endpoint changes
545
+ infra , err := util .GetInfrastructure (d .Listers .Infrastructures )
546
+ if err != nil {
547
+ return nil , err
548
+ }
549
+ d .setServiceEndpointOverrides (infra )
550
+
490
551
IAMAPIKey , err := d .getCredentialsConfigData ()
491
552
if err != nil {
492
553
return nil , err
493
554
}
494
555
495
- service , err := resourcecontrollerv2 .NewResourceControllerV2 (
496
- & resourcecontrollerv2.ResourceControllerV2Options {
497
- Authenticator : & core.IamAuthenticator {
498
- ApiKey : IAMAPIKey ,
499
- },
500
- },
501
- )
556
+ authenticator := & core.IamAuthenticator {
557
+ ApiKey : IAMAPIKey ,
558
+ }
559
+
560
+ if d .iamServiceEndpoint != "" {
561
+ authenticator .URL = d .iamServiceEndpoint
562
+ }
563
+
564
+ rcOptions := & resourcecontrollerv2.ResourceControllerV2Options {
565
+ Authenticator : authenticator ,
566
+ }
567
+ if d .rcServiceEndpoint != "" {
568
+ rcOptions .URL = d .rcServiceEndpoint
569
+ }
570
+
571
+ service , err := resourcecontrollerv2 .NewResourceControllerV2 (rcOptions )
502
572
if err != nil {
503
573
return nil , err
504
574
}
505
575
506
576
return service , nil
507
577
}
508
578
509
- // getResouceManagerService returns the IBM Cloud resource manager
510
- // client.
579
+ // getResourceManagerService returns the IBM Cloud resource manager client.
511
580
func (d * driver ) getResourceManagerService () (* resourcemanagerv2.ResourceManagerV2 , error ) {
512
581
if d .resourceManager != nil {
513
582
return d .resourceManager , nil
514
583
}
515
584
585
+ // Fetch the latest Infrastructure Status, for any endpoint changes
586
+ infra , err := util .GetInfrastructure (d .Listers .Infrastructures )
587
+ if err != nil {
588
+ return nil , err
589
+ }
590
+ d .setServiceEndpointOverrides (infra )
591
+
516
592
IAMAPIKey , err := d .getCredentialsConfigData ()
517
593
if err != nil {
518
594
return nil , err
519
595
}
520
596
521
- service , err := resourcemanagerv2 .NewResourceManagerV2 (
522
- & resourcemanagerv2.ResourceManagerV2Options {
523
- Authenticator : & core.IamAuthenticator {
524
- ApiKey : IAMAPIKey ,
525
- },
526
- },
527
- )
597
+ authenticator := & core.IamAuthenticator {
598
+ ApiKey : IAMAPIKey ,
599
+ }
600
+
601
+ if d .iamServiceEndpoint != "" {
602
+ authenticator .URL = d .iamServiceEndpoint
603
+ }
604
+
605
+ rmOptions := & resourcemanagerv2.ResourceManagerV2Options {
606
+ Authenticator : authenticator ,
607
+ }
608
+ if d .rmServiceEndpoint != "" {
609
+ rmOptions .URL = d .rmServiceEndpoint
610
+ }
611
+
612
+ service , err := resourcemanagerv2 .NewResourceManagerV2 (rmOptions )
528
613
if err != nil {
529
614
return nil , err
530
615
}
@@ -685,6 +770,7 @@ func (d *driver) bucketExists(bucketName string, serviceInstanceCRN string) erro
685
770
// getIBMCOSClient returns a client that allows us to interact
686
771
// with the IBM COS service.
687
772
func (d * driver ) getIBMCOSClient (serviceInstanceCRN string ) (* s3.S3 , error ) {
773
+ // Fetch the latest Infrastructure Status, for any endpoint changes
688
774
infra , err := util .GetInfrastructure (d .Listers .Infrastructures )
689
775
if err != nil {
690
776
return nil , err
@@ -702,20 +788,29 @@ func (d *driver) getIBMCOSClient(serviceInstanceCRN string) (*s3.S3, error) {
702
788
}
703
789
}
704
790
}
791
+ d .setServiceEndpointOverrides (infra )
705
792
706
793
if IBMCOSLocation == "" {
707
794
return nil , fmt .Errorf ("unable to get location from infrastructure" )
708
795
}
709
796
710
- serviceEndpoint := fmt .Sprintf ("s3.%s.cloud-object-storage.appdomain.cloud" , IBMCOSLocation )
797
+ cosServiceEndpoint := fmt .Sprintf (cosEndpointTemplate , IBMCOSLocation )
798
+ iamTokenEndpoint := IAMEndpoint
799
+ if d .cosServiceEndpoint != "" {
800
+ cosServiceEndpoint = d .cosServiceEndpoint
801
+ }
802
+ if d .iamServiceEndpoint != "" {
803
+ iamTokenEndpoint = fmt .Sprintf ("%s%s" , d .iamServiceEndpoint , IAMTokenPath )
804
+ }
805
+
711
806
IAMAPIKey , err := d .getCredentialsConfigData ()
712
807
if err != nil {
713
808
return nil , err
714
809
}
715
810
716
811
awsOptions := session.Options {
717
812
Config : aws.Config {
718
- Endpoint : & serviceEndpoint ,
813
+ Endpoint : & cosServiceEndpoint ,
719
814
Region : & d .Config .Location ,
720
815
HTTPClient : & http.Client {
721
816
Transport : & http.Transport {
@@ -742,7 +837,7 @@ func (d *driver) getIBMCOSClient(serviceInstanceCRN string) (*s3.S3, error) {
742
837
awsOptions .Config .Credentials = credentials .AnonymousCredentials
743
838
awsOptions .Config .HTTPClient .Transport = d .roundTripper
744
839
} else {
745
- awsOptions .Config .Credentials = ibmiam .NewStaticCredentials (aws .NewConfig (), IAMEndpoint , IAMAPIKey , serviceInstanceCRN )
840
+ awsOptions .Config .Credentials = ibmiam .NewStaticCredentials (aws .NewConfig (), iamTokenEndpoint , IAMAPIKey , serviceInstanceCRN )
746
841
}
747
842
748
843
sess , err := session .NewSessionWithOptions (awsOptions )
@@ -791,7 +886,7 @@ func (d *driver) VolumeSecrets() (map[string]string, error) {
791
886
}
792
887
793
888
// Get resource controller service
794
- rc , err := d .getResouceControllerService ()
889
+ rc , err := d .getResourceControllerService ()
795
890
if err != nil {
796
891
return nil , err
797
892
}
0 commit comments