Skip to content

Commit

Permalink
Prepare for Gophercloud TWO
Browse files Browse the repository at this point in the history
  • Loading branch information
spjmurray committed May 24, 2024
1 parent 5072ed1 commit d62614b
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 361 deletions.
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/go-chi/chi/v5 v5.0.12
github.com/go-logr/logr v1.4.1
github.com/google/uuid v1.6.0
github.com/gophercloud/gophercloud v1.11.0
github.com/gophercloud/gophercloud/v2 v2.0.0-beta.4
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56
github.com/prometheus/client_golang v1.19.0
github.com/spdx/tools-golang v0.5.3
Expand Down Expand Up @@ -78,6 +78,7 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/gophercloud/gophercloud v1.11.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
Expand Down Expand Up @@ -141,13 +142,13 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
Expand Down
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gophercloud/gophercloud v1.11.0 h1:ls0O747DIq1D8SUHc7r2vI8BFbMLeLFuENaAIfEx7OM=
github.com/gophercloud/gophercloud v1.11.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gophercloud/gophercloud/v2 v2.0.0-beta.4 h1:4514NhZKSyc2srbqWgyP85HVhjEv9c0kxwQcDSR1/YQ=
github.com/gophercloud/gophercloud/v2 v2.0.0-beta.4/go.mod h1:HbB8pJ/nycmlTRO++YTIFt9KUDx5c9gdaTFbk4oB5wA=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
Expand Down Expand Up @@ -370,8 +372,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
Expand Down Expand Up @@ -420,15 +422,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
Expand Down
86 changes: 86 additions & 0 deletions pkg/providers/openstack/blockstorage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
Copyright 2022-2024 EscherCloud.
Copyright 2024 the Unikorn Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package openstack

import (
"context"

"github.com/gophercloud/gophercloud/v2"
"github.com/gophercloud/gophercloud/v2/openstack"
"github.com/gophercloud/gophercloud/v2/openstack/blockstorage/v3/availabilityzones"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"

"github.com/unikorn-cloud/unikorn/pkg/constants"
)

// BlockStorageClient wraps the generic client because gophercloud is unsafe.
type BlockStorageClient struct {
client *gophercloud.ServiceClient
}

// NewBlockStorageClient provides a simple one-liner to start computing.
func NewBlockStorageClient(ctx context.Context, provider CredentialProvider) (*BlockStorageClient, error) {
providerClient, err := provider.Client(ctx)
if err != nil {
return nil, err
}

client, err := openstack.NewBlockStorageV3(providerClient, gophercloud.EndpointOpts{})
if err != nil {
return nil, err
}

c := &BlockStorageClient{
client: client,
}

return c, nil
}

// AvailabilityZones retrieves block storage availability zones.
func (c *BlockStorageClient) AvailabilityZones(ctx context.Context) ([]availabilityzones.AvailabilityZone, error) {
url := c.client.ServiceURL("os-availability-zone")

tracer := otel.GetTracerProvider().Tracer(constants.Application)

_, span := tracer.Start(ctx, url, trace.WithSpanKind(trace.SpanKindClient))
defer span.End()

pages, err := availabilityzones.List(c.client).AllPages(ctx)
if err != nil {
return nil, err
}

result, err := availabilityzones.ExtractAvailabilityZones(pages)
if err != nil {
return nil, err
}

filtered := []availabilityzones.AvailabilityZone{}

for _, az := range result {
if !az.ZoneState.Available {
continue
}

filtered = append(filtered, az)
}

return filtered, nil
}
61 changes: 16 additions & 45 deletions pkg/providers/openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ limitations under the License.
package openstack

import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/utils/openstack/clientconfig"
"context"

"github.com/gophercloud/gophercloud/v2"
"github.com/gophercloud/gophercloud/v2/openstack"
)

// authenticatedClient returns a provider client used to initialize service clients.
func authenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
func authenticatedClient(ctx context.Context, options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
// TODO: the JWT token issuer will cap the expiry at that of the
// keystone token, so we shouldn't get an unauthorized error. Just
// as well as we cannot disambiguate from what gophercloud returns.
client, err := openstack.AuthenticatedClient(options)
client, err := openstack.AuthenticatedClient(ctx, options)
if err != nil {
return nil, err
}
Expand All @@ -39,7 +40,7 @@ func authenticatedClient(options gophercloud.AuthOptions) (*gophercloud.Provider
// CredentialProvider abstracts authentication methods.
type CredentialProvider interface {
// Client returns a new provider client.
Client() (*gophercloud.ProviderClient, error)
Client(ctx context.Context) (*gophercloud.ProviderClient, error)
}

// ApplicationCredentialProvider allows use of an application credential.
Expand All @@ -63,15 +64,15 @@ func NewApplicationCredentialProvider(endpoint, id, secret string) *ApplicationC
}

// Client implements the Provider interface.
func (p *ApplicationCredentialProvider) Client() (*gophercloud.ProviderClient, error) {
func (p *ApplicationCredentialProvider) Client(ctx context.Context) (*gophercloud.ProviderClient, error) {
options := gophercloud.AuthOptions{
IdentityEndpoint: p.endpoint,
ApplicationCredentialID: p.id,
ApplicationCredentialSecret: p.secret,
AllowReauth: true,
}

return authenticatedClient(options)
return authenticatedClient(ctx, options)
}

// PasswordProvider allows use of an application credential.
Expand All @@ -97,7 +98,7 @@ func NewPasswordProvider(endpoint, userID, password, projectID string) *Password
}

// Client implements the Provider interface.
func (p *PasswordProvider) Client() (*gophercloud.ProviderClient, error) {
func (p *PasswordProvider) Client(ctx context.Context) (*gophercloud.ProviderClient, error) {
options := gophercloud.AuthOptions{
IdentityEndpoint: p.endpoint,
UserID: p.userID,
Expand All @@ -106,7 +107,7 @@ func (p *PasswordProvider) Client() (*gophercloud.ProviderClient, error) {
AllowReauth: true,
}

return authenticatedClient(options)
return authenticatedClient(ctx, options)
}

// DomainScopedPasswordProvider allows use of an application credential.
Expand All @@ -132,7 +133,7 @@ func NewDomainScopedPasswordProvider(endpoint, userID, password, domainID string
}

// Client implements the Provider interface.
func (p *DomainScopedPasswordProvider) Client() (*gophercloud.ProviderClient, error) {
func (p *DomainScopedPasswordProvider) Client(ctx context.Context) (*gophercloud.ProviderClient, error) {
options := gophercloud.AuthOptions{
IdentityEndpoint: p.endpoint,
UserID: p.userID,
Expand All @@ -143,7 +144,7 @@ func (p *DomainScopedPasswordProvider) Client() (*gophercloud.ProviderClient, er
AllowReauth: true,
}

return authenticatedClient(options)
return authenticatedClient(ctx, options)
}

// TokenProvider creates a client from an endpoint and token.
Expand All @@ -168,44 +169,14 @@ func NewTokenProvider(endpoint, token string) *TokenProvider {
}

// Client implements the Provider interface.
func (p *TokenProvider) Client() (*gophercloud.ProviderClient, error) {
func (p *TokenProvider) Client(ctx context.Context) (*gophercloud.ProviderClient, error) {
options := gophercloud.AuthOptions{
IdentityEndpoint: p.endpoint,
TokenID: p.token,
AllowReauth: true,
}

return authenticatedClient(options)
}

// CloudsProvider cretes a client from clouds.yaml.
type CloudsProvider struct {
// cloud is the key to lookup in clouds.yaml.
cloud string
}

// Ensure the interface is implemented.
var _ CredentialProvider = &CloudsProvider{}

// NewTokenProvider returns a new initialized provider.
func NewCloudsProvider(cloud string) *CloudsProvider {
return &CloudsProvider{
cloud: cloud,
}
}

// Client implements the Provider interface.
func (p *CloudsProvider) Client() (*gophercloud.ProviderClient, error) {
clientOpts := &clientconfig.ClientOpts{
Cloud: p.cloud,
}

options, err := clientconfig.AuthOptions(clientOpts)
if err != nil {
return nil, err
}

return authenticatedClient(*options)
return authenticatedClient(ctx, options)
}

// UnauthenticatedProvider is used for token issue.
Expand All @@ -226,7 +197,7 @@ func NewUnauthenticatedProvider(endpoint string) *UnauthenticatedProvider {
}

// Client implements the Provider interface.
func (p *UnauthenticatedProvider) Client() (*gophercloud.ProviderClient, error) {
func (p *UnauthenticatedProvider) Client(ctx context.Context) (*gophercloud.ProviderClient, error) {
client, err := openstack.NewClient(p.endpoint)
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit d62614b

Please sign in to comment.