@@ -25,6 +25,7 @@ import (
2525
2626 "github.com/gophercloud/gophercloud"
2727 "github.com/gophercloud/gophercloud/openstack"
28+ "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
2829 osclient "github.com/gophercloud/utils/client"
2930 "github.com/gophercloud/utils/openstack/clientconfig"
3031 corev1 "k8s.io/api/core/v1"
@@ -34,43 +35,42 @@ import (
3435 "sigs.k8s.io/yaml"
3536
3637 infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
37- "sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
3838)
3939
4040const (
4141 cloudsSecretKey = "clouds.yaml"
4242 caSecretKey = "cacert"
4343)
4444
45- func NewClientFromMachine (ctx context.Context , ctrlClient client.Client , openStackMachine * infrav1.OpenStackMachine ) (* gophercloud.ProviderClient , * clientconfig.ClientOpts , error ) {
45+ func NewClientFromMachine (ctx context.Context , ctrlClient client.Client , openStackMachine * infrav1.OpenStackMachine ) (* gophercloud.ProviderClient , * clientconfig.ClientOpts , string , error ) {
4646 var cloud clientconfig.Cloud
4747 var caCert []byte
4848
4949 if openStackMachine .Spec .IdentityRef != nil {
5050 var err error
5151 cloud , caCert , err = getCloudFromSecret (ctx , ctrlClient , openStackMachine .Namespace , openStackMachine .Spec .IdentityRef .Name , openStackMachine .Spec .CloudName )
5252 if err != nil {
53- return nil , nil , err
53+ return nil , nil , "" , err
5454 }
5555 }
5656 return NewClient (cloud , caCert )
5757}
5858
59- func NewClientFromCluster (ctx context.Context , ctrlClient client.Client , openStackCluster * infrav1.OpenStackCluster ) (* gophercloud.ProviderClient , * clientconfig.ClientOpts , error ) {
59+ func NewClientFromCluster (ctx context.Context , ctrlClient client.Client , openStackCluster * infrav1.OpenStackCluster ) (* gophercloud.ProviderClient , * clientconfig.ClientOpts , string , error ) {
6060 var cloud clientconfig.Cloud
6161 var caCert []byte
6262
6363 if openStackCluster .Spec .IdentityRef != nil {
6464 var err error
6565 cloud , caCert , err = getCloudFromSecret (ctx , ctrlClient , openStackCluster .Namespace , openStackCluster .Spec .IdentityRef .Name , openStackCluster .Spec .CloudName )
6666 if err != nil {
67- return nil , nil , err
67+ return nil , nil , "" , err
6868 }
6969 }
7070 return NewClient (cloud , caCert )
7171}
7272
73- func NewClient (cloud clientconfig.Cloud , caCert []byte ) (* gophercloud.ProviderClient , * clientconfig.ClientOpts , error ) {
73+ func NewClient (cloud clientconfig.Cloud , caCert []byte ) (* gophercloud.ProviderClient , * clientconfig.ClientOpts , string , error ) {
7474 clientOpts := new (clientconfig.ClientOpts )
7575 if cloud .AuthInfo != nil {
7676 clientOpts .AuthInfo = cloud .AuthInfo
@@ -80,13 +80,13 @@ func NewClient(cloud clientconfig.Cloud, caCert []byte) (*gophercloud.ProviderCl
8080
8181 opts , err := clientconfig .AuthOptions (clientOpts )
8282 if err != nil {
83- return nil , nil , fmt .Errorf ("auth option failed for cloud %v: %v" , cloud .Cloud , err )
83+ return nil , nil , "" , fmt .Errorf ("auth option failed for cloud %v: %v" , cloud .Cloud , err )
8484 }
8585 opts .AllowReauth = true
8686
8787 provider , err := openstack .NewClient (opts .IdentityEndpoint )
8888 if err != nil {
89- return nil , nil , fmt .Errorf ("create providerClient err: %v" , err )
89+ return nil , nil , "" , fmt .Errorf ("create providerClient err: %v" , err )
9090 }
9191
9292 config := & tls.Config {
@@ -109,9 +109,15 @@ func NewClient(cloud clientconfig.Cloud, caCert []byte) (*gophercloud.ProviderCl
109109 }
110110 err = openstack .Authenticate (provider , * opts )
111111 if err != nil {
112- return nil , nil , fmt .Errorf ("providerClient authentication err: %v" , err )
112+ return nil , nil , "" , fmt .Errorf ("providerClient authentication err: %v" , err )
113113 }
114- return provider , clientOpts , nil
114+
115+ projectID , err := getProjectIDFromAuthResult (provider .GetAuthResult ())
116+ if err != nil {
117+ return nil , nil , "" , err
118+ }
119+
120+ return provider , clientOpts , projectID , nil
115121}
116122
117123type defaultLogger struct {}
@@ -161,42 +167,20 @@ func getCloudFromSecret(ctx context.Context, ctrlClient client.Client, secretNam
161167 return clouds .Clouds [cloudName ], caCert , nil
162168}
163169
164- type project struct {
165- ID string `json:"id"`
166- Name string
167- }
168-
169- type projects struct {
170- Projects []project `json:"projects"`
171- }
172-
173- func GetProjectID (client * gophercloud.ProviderClient , clientOpts * clientconfig.ClientOpts ) (string , error ) {
174- if clientOpts .AuthInfo .ProjectID != "" {
175- return clientOpts .AuthInfo .ProjectID , nil
176- }
177-
178- projectName := clientOpts .AuthInfo .ProjectName
179- if projectName == "" {
180- return "" , fmt .Errorf ("failed to get project id" )
181- }
182-
183- c , err := openstack .NewIdentityV3 (client , gophercloud.EndpointOpts {})
184- if err != nil {
185- return "" , fmt .Errorf ("failed to create identity service client: %v" , err )
186- }
170+ // getProjectIDFromAuthResult handles different auth mechanisms to retrieve the
171+ // current project id. Usually we use the Identity v3 Token mechanism that
172+ // returns the project id in the response to the initial auth request.
173+ func getProjectIDFromAuthResult (authResult gophercloud.AuthResult ) (string , error ) {
174+ switch authResult := authResult .(type ) {
175+ case tokens.CreateResult :
176+ project , err := authResult .ExtractProject ()
177+ if err != nil {
178+ return "" , fmt .Errorf ("unable to extract project from CreateResult: %v" , err )
179+ }
187180
188- jsonResp := projects {}
189- mc := metrics .NewMetricPrometheusContext ("project" , "get" )
190- resp , err := c .Get (c .ServiceURL ("auth" , "projects" ), & jsonResp , & gophercloud.RequestOpts {OkCodes : []int {200 }})
191- if mc .ObserveRequest (err ) != nil {
192- return "" , err
193- }
194- defer resp .Body .Close ()
181+ return project .ID , nil
195182
196- for _ , project := range jsonResp .Projects {
197- if project .Name == projectName {
198- return project .ID , nil
199- }
183+ default :
184+ return "" , fmt .Errorf ("unable to get the project id from auth response with type %T" , authResult )
200185 }
201- return "" , fmt .Errorf ("project %s not found" , projectName )
202186}
0 commit comments