Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update backupbucket fields #931

Merged
merged 2 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions hack/api-reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</p>
Resource Types:
<ul><li>
<a href="#azure.provider.extensions.gardener.cloud/v1alpha1.BackupConfig">BackupConfig</a>
<a href="#azure.provider.extensions.gardener.cloud/v1alpha1.BackupBucketConfig">BackupBucketConfig</a>
</li><li>
<a href="#azure.provider.extensions.gardener.cloud/v1alpha1.CloudProfileConfig">CloudProfileConfig</a>
</li><li>
Expand All @@ -24,10 +24,10 @@ Resource Types:
</li><li>
<a href="#azure.provider.extensions.gardener.cloud/v1alpha1.WorkerStatus">WorkerStatus</a>
</li></ul>
<h3 id="azure.provider.extensions.gardener.cloud/v1alpha1.BackupConfig">BackupConfig
<h3 id="azure.provider.extensions.gardener.cloud/v1alpha1.BackupBucketConfig">BackupBucketConfig
</h3>
<p>
<p>BackupConfig is the provider-specific configuration for backup buckets/entries</p>
<p>BackupBucketConfig is the provider-specific configuration for backup buckets/entries</p>
</p>
<table>
<thead>
Expand All @@ -52,7 +52,7 @@ azure.provider.extensions.gardener.cloud/v1alpha1
<code>kind</code></br>
string
</td>
<td><code>BackupConfig</code></td>
<td><code>BackupBucketConfig</code></td>
</tr>
<tr>
<td>
Expand Down Expand Up @@ -605,7 +605,7 @@ string
</h3>
<p>
(<em>Appears on:</em>
<a href="#azure.provider.extensions.gardener.cloud/v1alpha1.BackupConfig">BackupConfig</a>,
<a href="#azure.provider.extensions.gardener.cloud/v1alpha1.BackupBucketConfig">BackupBucketConfig</a>,
<a href="#azure.provider.extensions.gardener.cloud/v1alpha1.CloudProfileConfig">CloudProfileConfig</a>,
<a href="#azure.provider.extensions.gardener.cloud/v1alpha1.DNSRecordConfig">DNSRecordConfig</a>)
</p>
Expand Down
8 changes: 4 additions & 4 deletions pkg/apis/azure/helper/scheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ func CloudProfileConfigFromCluster(cluster *controller.Cluster) (*api.CloudProfi
}

// BackupConfigFromBackupBucket decodes the provider specific config from a given BackupBucket object.
func BackupConfigFromBackupBucket(backupBucket *extensionsv1alpha1.BackupBucket) (api.BackupConfig, error) {
backupConfig := api.BackupConfig{}
func BackupConfigFromBackupBucket(backupBucket *extensionsv1alpha1.BackupBucket) (api.BackupBucketConfig, error) {
backupConfig := api.BackupBucketConfig{}
if backupBucket != nil && backupBucket.Spec.ProviderConfig != nil {
bucketJson, err := backupBucket.Spec.ProviderConfig.MarshalJSON()
if err != nil {
Expand All @@ -99,8 +99,8 @@ func BackupConfigFromBackupBucket(backupBucket *extensionsv1alpha1.BackupBucket)
}

// BackupConfigFromBackupEntry decodes the provider specific config from a given BackupEntry object.
func BackupConfigFromBackupEntry(backupEntry *extensionsv1alpha1.BackupEntry) (api.BackupConfig, error) {
backupConfig := api.BackupConfig{}
func BackupConfigFromBackupEntry(backupEntry *extensionsv1alpha1.BackupEntry) (api.BackupBucketConfig, error) {
backupConfig := api.BackupBucketConfig{}
if backupEntry != nil && backupEntry.Spec.DefaultSpec.ProviderConfig != nil {
entryJson, err := backupEntry.Spec.ProviderConfig.MarshalJSON()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/azure/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ControlPlaneConfig{},
&WorkerStatus{},
&WorkerConfig{},
&BackupConfig{},
&BackupBucketConfig{},
&DNSRecordConfig{},
)
return nil
Expand Down
4 changes: 2 additions & 2 deletions pkg/apis/azure/types_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// BackupConfig is the provider-specific configuration for backup buckets/entries
type BackupConfig struct {
// BackupBucketConfig is the provider-specific configuration for backup buckets/entries
type BackupBucketConfig struct {
metav1.TypeMeta
// CloudConfiguration contains config that controls which cloud to connect to.
CloudConfiguration *CloudConfiguration
Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/azure/v1alpha1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ControlPlaneConfig{},
&WorkerConfig{},
&WorkerStatus{},
&BackupConfig{},
&BackupBucketConfig{},
&DNSRecordConfig{},
)
return nil
Expand Down
4 changes: 2 additions & 2 deletions pkg/apis/azure/v1alpha1/types_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// BackupConfig is the provider-specific configuration for backup buckets/entries
type BackupConfig struct {
// BackupBucketConfig is the provider-specific configuration for backup buckets/entries
type BackupBucketConfig struct {
metav1.TypeMeta `json:",inline"`
// CloudConfiguration contains config that controls which cloud to connect to.
// +optional
Expand Down
24 changes: 12 additions & 12 deletions pkg/apis/azure/v1alpha1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions pkg/apis/azure/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions pkg/apis/azure/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 0 additions & 41 deletions pkg/azure/client/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@ package client

import (
"context"
"fmt"
"strings"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/gardener/gardener-extension-provider-azure/pkg/apis/azure"
"github.com/gardener/gardener-extension-provider-azure/pkg/internal"
)

Expand Down Expand Up @@ -166,41 +163,3 @@ func (f azureFactory) ManagedUserIdentity() (ManagedUserIdentity, error) {
func (f azureFactory) VirtualMachineImages() (VirtualMachineImages, error) {
return NewVirtualMachineImagesClient(f.auth, f.tokenCredential, f.clientOpts)
}

// NewBlobStorageClient reads the secret from the passed reference and return an Azure (blob) storage client.
func NewBlobStorageClient(ctx context.Context, c client.Client, secretRef corev1.SecretReference, cloudConfiguration *azure.CloudConfiguration) (BlobStorage, error) {
var storageDomain string

// Unfortunately the valid values for storage domains run by Microsoft do not seem to be part of any sdk module. They might be queryable from the cloud configuration,
// but I also haven't been able to find a documented list of proper ServiceName values.
// Furthermore, it seems there is still no unified way of specifying the cloud instance to connect to as the domain remains part of the storage account URL while
// the new options _also_ allow configuring the cloud instance.
// For the time being (until further testing can be done) I assume that the instance that is pointed at by the URL wins so let's keep the old logic for building the
// service URL.
if cloudConfiguration == nil {
storageDomain = "blob.core.windows.net"
} else {
cloudConfigurationName := cloudConfiguration.Name
switch {
case strings.EqualFold(cloudConfigurationName, "AzurePublic"):
storageDomain = "blob.core.windows.net"
case strings.EqualFold(cloudConfigurationName, "AzureGovernment"):
// Note: This differs from the one mentioned in the docs ("blob.core.govcloudapi.net") but should be the right one.
// ref.: https://github.com/google/go-cloud/blob/be1b4aee38955e1b8cd1c46f8f47fb6f9d820a9b/blob/azureblob/azureblob.go#L162
storageDomain = "blob.core.usgovcloudapi.net"
case strings.EqualFold(cloudConfigurationName, "AzureChina"):
// This is an educated guess
storageDomain = "blob.core.chinacloudapi.cn"

default:
return nil, fmt.Errorf("unknown cloud configuration name '%s'", cloudConfigurationName)
}
}

blobStorageClient, err := newStorageClient(ctx, c, &secretRef, storageDomain)
if err != nil {
return nil, err
}

return blobStorageClient, nil
}
56 changes: 43 additions & 13 deletions pkg/azure/client/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"fmt"
"net/url"
"strings"

"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
Expand All @@ -17,6 +18,7 @@ import (
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"

azureapi "github.com/gardener/gardener-extension-provider-azure/pkg/apis/azure"
"github.com/gardener/gardener-extension-provider-azure/pkg/azure"
)

Expand All @@ -28,9 +30,44 @@ type BlobStorageClient struct {
client *azblob.Client
}

// newStorageClient creates a client for an Azure Blob storage by reading auth information from secret reference. Requires passing the storage domain (formerly
// BlobStorageDomainFromCloudConfiguration returns the storage service domain given a known cloudConfiguration.
func BlobStorageDomainFromCloudConfiguration(cloudConfiguration *azureapi.CloudConfiguration) (string, error) {
// Unfortunately the valid values for storage domains run by Microsoft do not seem to be part of any sdk module. They might be queryable from the cloud configuration,
// but I also haven't been able to find a documented list of proper ServiceName values.
// Furthermore, it seems there is still no unified way of specifying the cloud instance to connect to as the domain remains part of the storage account URL while
// the new options _also_ allow configuring the cloud instance.
switch {
case cloudConfiguration == nil || strings.EqualFold(cloudConfiguration.Name, "AzurePublic"):
return azure.AzureBlobStorageDomain, nil
case strings.EqualFold(cloudConfiguration.Name, "AzureGovernment"):
// Note: This differs from the one mentioned in the docs ("blob.core.govcloudapi.net") but should be the right one.
// ref.: https://github.com/google/go-cloud/blob/be1b4aee38955e1b8cd1c46f8f47fb6f9d820a9b/blob/azureblob/azureblob.go#L162
return azure.AzureUSGovBlobStorageDomain, nil
case strings.EqualFold(cloudConfiguration.Name, "AzureChina"):
// source: https://learn.microsoft.com/en-us/azure/china/resources-developer-guide#check-endpoints-in-azure
return azure.AzureChinaBlobStorageDomain, nil
}
return "", fmt.Errorf("unknown cloud configuration name '%s'", cloudConfiguration.Name)
}

// NewBlobStorageClient creates a blob storage client.
func NewBlobStorageClient(_ context.Context, storageAccountName, storageAccountKey, storageDomain string) (*BlobStorageClient, error) {
credentials, err := azblob.NewSharedKeyCredential(storageAccountName, storageAccountKey)
if err != nil {
return nil, fmt.Errorf("failed to create shared key credentials: %v", err)
}

storageEndpointURL, err := url.Parse(fmt.Sprintf("https://%s.%s", storageAccountName, storageDomain))
if err != nil {
return nil, fmt.Errorf("failed to parse service url: %v", err)
}
blobclient, err := azblob.NewClientWithSharedKeyCredential(storageEndpointURL.String(), credentials, nil)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the azure-sdk-for-go the nomenclature is a bit different. They provide 3 different clients AFAIK:

  1. Blob client which is created with a specific blob URL (see here)
  2. Container client which is created for a specific container/bucket ( see here).
  3. Service client to manage buckets/containers (see here)

So what you have here is a ContainerClient or a BucketClient but you call it a blobClient. This confused me a bit.

Copy link
Contributor Author

@kon-angelo kon-angelo Aug 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to look closer for that one. The blob client that we use, creates all the clients internally, so e.g. from the interfaces that we use the azure SDK does something like:

func (c *Client) DeleteBlob(ctx context.Context, containerName string, blobName string, o *DeleteBlobOptions) (DeleteBlobResponse, error) {
	return c.svc.NewContainerClient(containerName).NewBlobClient(blobName).Delete(ctx, o)
}

So from our perspective we only use the top level interfaces and all the container/bucket client is hidden from us - I guess that's why the name was blobClient. I will think how to do the names better.

return &BlobStorageClient{blobclient}, err
}

// NewBlobStorageClientFromSecretRef creates a client for an Azure Blob storage by reading auth information from secret reference. Requires passing the storage domain (formerly
// blobstorage host name) to determine the endpoint to build the service url for.
func newStorageClient(ctx context.Context, client client.Client, secretRef *corev1.SecretReference, storageDomain string) (*BlobStorageClient, error) {
func NewBlobStorageClientFromSecretRef(ctx context.Context, client client.Client, secretRef *corev1.SecretReference) (*BlobStorageClient, error) {
secret, err := extensionscontroller.GetSecretByReference(ctx, client, secretRef)
if err != nil {
return nil, err
Expand All @@ -45,19 +82,12 @@ func newStorageClient(ctx context.Context, client client.Client, secretRef *core
return nil, fmt.Errorf("secret %s/%s doesn't have a storage key", secret.Namespace, secret.Name)
}

credentials, err := azblob.NewSharedKeyCredential(string(storageAccountName), string(storageAccountKey))
if err != nil {
return nil, fmt.Errorf("failed to create shared key credentials: %v", err)
}

storageAccountURL, err := url.Parse(fmt.Sprintf("https://%s.%s", storageAccountName, storageDomain))
if err != nil {
return nil, fmt.Errorf("failed to parse service url: %v", err)
storageDomain := azure.AzureBlobStorageDomain
if v, ok := secret.Data[azure.StorageDomain]; ok {
storageDomain = string(v)
}

blobclient, err := azblob.NewClientWithSharedKeyCredential(storageAccountURL.String(), credentials, nil)
return &BlobStorageClient{blobclient}, err

return NewBlobStorageClient(ctx, string(storageAccountName), string(storageAccountKey), storageDomain)
}

// DeleteObjectsWithPrefix deletes the blob objects with the specific <prefix> from <container>.
Expand Down
10 changes: 8 additions & 2 deletions pkg/azure/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,15 @@ const (
StorageAccount = "storageAccount"
// StorageKey is a constant for the key in a cloud provider secret and backup secret that holds the Azure secret storage access key.
StorageKey = "storageKey"
// StorageDomain is a constant for the key in a backup secret that holds the domain for the Azure blob storage service.
StorageDomain = "domain"

// AzureBlobStorageHostName is the host name for azure blob storage service.
AzureBlobStorageHostName = "blob.core.windows.net"
// AzureBlobStorageDomain is the host name for azure blob storage service.
AzureBlobStorageDomain = "blob.core.windows.net"
// AzureChinaBlobStorageDomain is the host name for azure blob storage service for the Chinese regions.
AzureChinaBlobStorageDomain = "blob.core.chinacloudapi.cn"
// AzureUSGovBlobStorageDomain is the host name for azure blob storage service for the US Government regions.
AzureUSGovBlobStorageDomain = "blob.core.usgovcloudapi.net"

// MachineSetTagKey is the name of the infrastructure resource tag for machine sets.
MachineSetTagKey = "machineset.azure.extensions.gardener.cloud"
Expand Down
Loading
Loading