get rid of StorageAdapter structs and move validation into block/object

Signed-off-by: Steve Kriss <steve@heptio.com>
pull/43/head
Steve Kriss 2017-08-15 13:20:23 -07:00
parent ebc06fd632
commit 8d5c8ffcbb
11 changed files with 324 additions and 386 deletions

View File

@ -17,8 +17,11 @@ limitations under the License.
package aws
import (
"errors"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"k8s.io/apimachinery/pkg/util/sets"
@ -33,6 +36,53 @@ type blockStorageAdapter struct {
az string
}
func getSession(config *aws.Config) (*session.Session, error) {
sess, err := session.NewSession(config)
if err != nil {
return nil, err
}
if _, err := sess.Config.Credentials.Get(); err != nil {
return nil, err
}
return sess, nil
}
func NewBlockStorageAdapter(region, availabilityZone string) (cloudprovider.BlockStorageAdapter, error) {
if region == "" {
return nil, errors.New("missing region in aws configuration in config file")
}
if availabilityZone == "" {
return nil, errors.New("missing availabilityZone in aws configuration in config file")
}
awsConfig := aws.NewConfig().WithRegion(region)
sess, err := getSession(awsConfig)
if err != nil {
return nil, err
}
// validate the availabilityZone
var (
ec2Client = ec2.New(sess)
azReq = &ec2.DescribeAvailabilityZonesInput{ZoneNames: []*string{&availabilityZone}}
)
res, err := ec2Client.DescribeAvailabilityZones(azReq)
if err != nil {
return nil, err
}
if len(res.AvailabilityZones) == 0 {
return nil, fmt.Errorf("availability zone %q not found", availabilityZone)
}
return &blockStorageAdapter{
ec2: ec2Client,
az: availabilityZone,
}, nil
}
// iopsVolumeTypes is a set of AWS EBS volume types for which IOPS should
// be captured during snapshot and provided when creating a new volume
// from snapshot.

View File

@ -17,9 +17,11 @@ limitations under the License.
package aws
import (
"errors"
"io"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/heptio/ark/pkg/cloudprovider"
@ -32,6 +34,40 @@ type objectStorageAdapter struct {
kmsKeyID string
}
func NewObjectStorageAdapter(region, s3URL, kmsKeyID string, s3ForcePathStyle bool) (cloudprovider.ObjectStorageAdapter, error) {
if region == "" {
return nil, errors.New("missing region in aws configuration in config file")
}
awsConfig := aws.NewConfig().
WithRegion(region).
WithS3ForcePathStyle(s3ForcePathStyle)
if s3URL != "" {
awsConfig = awsConfig.WithEndpointResolver(
endpoints.ResolverFunc(func(service, region string, optFns ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) {
if service == endpoints.S3ServiceID {
return endpoints.ResolvedEndpoint{
URL: s3URL,
}, nil
}
return endpoints.DefaultResolver().EndpointFor(service, region, optFns...)
}),
)
}
sess, err := getSession(awsConfig)
if err != nil {
return nil, err
}
return &objectStorageAdapter{
s3: s3.New(sess),
kmsKeyID: kmsKeyID,
}, nil
}
func (op *objectStorageAdapter) PutObject(bucket string, key string, body io.ReadSeeker) error {
req := &s3.PutObjectInput{
Bucket: &bucket,

View File

@ -1,78 +0,0 @@
/*
Copyright 2017 Heptio Inc.
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 aws
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/heptio/ark/pkg/cloudprovider"
)
type storageAdapter struct {
blockStorage *blockStorageAdapter
objectStorage *objectStorageAdapter
}
var _ cloudprovider.StorageAdapter = &storageAdapter{}
func NewStorageAdapter(config *aws.Config, availabilityZone string, kmsKeyID string) (cloudprovider.StorageAdapter, error) {
sess, err := session.NewSession(config)
if err != nil {
return nil, err
}
if _, err := sess.Config.Credentials.Get(); err != nil {
return nil, err
}
// validate the availabilityZone
var (
ec2Client = ec2.New(sess)
azReq = &ec2.DescribeAvailabilityZonesInput{ZoneNames: []*string{&availabilityZone}}
)
res, err := ec2Client.DescribeAvailabilityZones(azReq)
if err != nil {
return nil, err
}
if len(res.AvailabilityZones) == 0 {
return nil, fmt.Errorf("availability zone %q not found", availabilityZone)
}
return &storageAdapter{
blockStorage: &blockStorageAdapter{
ec2: ec2Client,
az: availabilityZone,
},
objectStorage: &objectStorageAdapter{
s3: s3.New(sess),
kmsKeyID: kmsKeyID,
},
}, nil
}
func (op *storageAdapter) ObjectStorage() cloudprovider.ObjectStorageAdapter {
return op.objectStorage
}
func (op *storageAdapter) BlockStorage() cloudprovider.BlockStorageAdapter {
return op.blockStorage
}

View File

@ -20,17 +20,21 @@ import (
"context"
"errors"
"fmt"
"os"
"time"
azure "github.com/Azure/azure-sdk-for-go/arm/disk"
"github.com/Azure/azure-sdk-for-go/arm/disk"
"github.com/Azure/azure-sdk-for-go/arm/examples/helpers"
"github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/satori/uuid"
"github.com/heptio/ark/pkg/cloudprovider"
)
type blockStorageAdapter struct {
disks *azure.DisksClient
snaps *azure.SnapshotsClient
disks *disk.DisksClient
snaps *disk.SnapshotsClient
subscription string
resourceGroup string
location string
@ -39,19 +43,104 @@ type blockStorageAdapter struct {
var _ cloudprovider.BlockStorageAdapter = &blockStorageAdapter{}
const (
azureClientIDKey string = "AZURE_CLIENT_ID"
azureClientSecretKey string = "AZURE_CLIENT_SECRET"
azureSubscriptionIDKey string = "AZURE_SUBSCRIPTION_ID"
azureTenantIDKey string = "AZURE_TENANT_ID"
azureStorageAccountIDKey string = "AZURE_STORAGE_ACCOUNT_ID"
azureStorageKeyKey string = "AZURE_STORAGE_KEY"
azureResourceGroupKey string = "AZURE_RESOURCE_GROUP"
)
func getConfig() map[string]string {
cfg := map[string]string{
azureClientIDKey: "",
azureClientSecretKey: "",
azureSubscriptionIDKey: "",
azureTenantIDKey: "",
azureStorageAccountIDKey: "",
azureStorageKeyKey: "",
azureResourceGroupKey: "",
}
for key := range cfg {
cfg[key] = os.Getenv(key)
}
return cfg
}
func NewBlockStorageAdapter(location string, apiTimeout time.Duration) (cloudprovider.BlockStorageAdapter, error) {
if location == "" {
return nil, errors.New("missing location in azure configuration in config file")
}
if apiTimeout == 0 {
apiTimeout = time.Minute
}
cfg := getConfig()
spt, err := helpers.NewServicePrincipalTokenFromCredentials(cfg, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
return nil, fmt.Errorf("error creating new service principal: %v", err)
}
disksClient := disk.NewDisksClient(cfg[azureSubscriptionIDKey])
snapsClient := disk.NewSnapshotsClient(cfg[azureSubscriptionIDKey])
disksClient.Authorizer = spt
snapsClient.Authorizer = spt
// validate the location
groupClient := subscriptions.NewGroupClient()
groupClient.Authorizer = spt
locs, err := groupClient.ListLocations(cfg[azureSubscriptionIDKey])
if err != nil {
return nil, err
}
if locs.Value == nil {
return nil, errors.New("no locations returned from Azure API")
}
locationExists := false
for _, loc := range *locs.Value {
if (loc.Name != nil && *loc.Name == location) || (loc.DisplayName != nil && *loc.DisplayName == location) {
locationExists = true
break
}
}
if !locationExists {
return nil, fmt.Errorf("location %q not found", location)
}
return &blockStorageAdapter{
disks: &disksClient,
snaps: &snapsClient,
subscription: cfg[azureSubscriptionIDKey],
resourceGroup: cfg[azureResourceGroupKey],
location: location,
apiTimeout: apiTimeout,
}, nil
}
func (op *blockStorageAdapter) CreateVolumeFromSnapshot(snapshotID, volumeType string, iops *int64) (string, error) {
fullSnapshotName := getFullSnapshotName(op.subscription, op.resourceGroup, snapshotID)
diskName := "restore-" + uuid.NewV4().String()
disk := azure.Model{
disk := disk.Model{
Name: &diskName,
Location: &op.location,
Properties: &azure.Properties{
CreationData: &azure.CreationData{
CreateOption: azure.Copy,
Properties: &disk.Properties{
CreationData: &disk.CreationData{
CreateOption: disk.Copy,
SourceResourceID: &fullSnapshotName,
},
AccountType: azure.StorageAccountTypes(volumeType),
AccountType: disk.StorageAccountTypes(volumeType),
},
}
@ -136,11 +225,11 @@ func (op *blockStorageAdapter) CreateSnapshot(volumeID string, tags map[string]s
snapshotName = volumeID[0:80-len(suffix)] + suffix
}
snap := azure.Snapshot{
snap := disk.Snapshot{
Name: &snapshotName,
Properties: &azure.Properties{
CreationData: &azure.CreationData{
CreateOption: azure.Copy,
Properties: &disk.Properties{
CreationData: &disk.CreationData{
CreateOption: disk.Copy,
SourceResourceID: &fullDiskName,
},
},

View File

@ -34,6 +34,21 @@ type objectStorageAdapter struct {
var _ cloudprovider.ObjectStorageAdapter = &objectStorageAdapter{}
func NewObjectStorageAdapter() (cloudprovider.ObjectStorageAdapter, error) {
cfg := getConfig()
storageClient, err := storage.NewBasicClient(cfg[azureStorageAccountIDKey], cfg[azureStorageKeyKey])
if err != nil {
return nil, err
}
blobClient := storageClient.GetBlobService()
return &objectStorageAdapter{
blobClient: &blobClient,
}, nil
}
func (op *objectStorageAdapter) PutObject(bucket string, key string, body io.ReadSeeker) error {
container, err := getContainerReference(op.blobClient, bucket)
if err != nil {

View File

@ -1,130 +0,0 @@
/*
Copyright 2017 Heptio Inc.
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 azure
import (
"errors"
"fmt"
"os"
"time"
"github.com/Azure/azure-sdk-for-go/arm/disk"
"github.com/Azure/azure-sdk-for-go/arm/examples/helpers"
"github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions"
"github.com/Azure/azure-sdk-for-go/storage"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/heptio/ark/pkg/cloudprovider"
)
const (
azureClientIDKey string = "AZURE_CLIENT_ID"
azureClientSecretKey string = "AZURE_CLIENT_SECRET"
azureSubscriptionIDKey string = "AZURE_SUBSCRIPTION_ID"
azureTenantIDKey string = "AZURE_TENANT_ID"
azureStorageAccountIDKey string = "AZURE_STORAGE_ACCOUNT_ID"
azureStorageKeyKey string = "AZURE_STORAGE_KEY"
azureResourceGroupKey string = "AZURE_RESOURCE_GROUP"
)
type storageAdapter struct {
objectStorage *objectStorageAdapter
blockStorage *blockStorageAdapter
}
var _ cloudprovider.StorageAdapter = &storageAdapter{}
func NewStorageAdapter(location string, apiTimeout time.Duration) (cloudprovider.StorageAdapter, error) {
cfg := map[string]string{
azureClientIDKey: "",
azureClientSecretKey: "",
azureSubscriptionIDKey: "",
azureTenantIDKey: "",
azureStorageAccountIDKey: "",
azureStorageKeyKey: "",
azureResourceGroupKey: "",
}
for key := range cfg {
cfg[key] = os.Getenv(key)
}
spt, err := helpers.NewServicePrincipalTokenFromCredentials(cfg, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
return nil, fmt.Errorf("error creating new service principal: %v", err)
}
disksClient := disk.NewDisksClient(cfg[azureSubscriptionIDKey])
snapsClient := disk.NewSnapshotsClient(cfg[azureSubscriptionIDKey])
disksClient.Authorizer = spt
snapsClient.Authorizer = spt
storageClient, _ := storage.NewBasicClient(cfg[azureStorageAccountIDKey], cfg[azureStorageKeyKey])
blobClient := storageClient.GetBlobService()
if apiTimeout == 0 {
apiTimeout = time.Minute
}
// validate the location
groupClient := subscriptions.NewGroupClient()
groupClient.Authorizer = spt
locs, err := groupClient.ListLocations(cfg[azureSubscriptionIDKey])
if err != nil {
return nil, err
}
if locs.Value == nil {
return nil, errors.New("no locations returned from Azure API")
}
locationExists := false
for _, loc := range *locs.Value {
if (loc.Name != nil && *loc.Name == location) || (loc.DisplayName != nil && *loc.DisplayName == location) {
locationExists = true
break
}
}
if !locationExists {
return nil, fmt.Errorf("location %q not found", location)
}
return &storageAdapter{
objectStorage: &objectStorageAdapter{
blobClient: &blobClient,
},
blockStorage: &blockStorageAdapter{
disks: &disksClient,
snaps: &snapsClient,
subscription: cfg[azureSubscriptionIDKey],
resourceGroup: cfg[azureResourceGroupKey],
location: location,
apiTimeout: apiTimeout,
},
}, nil
}
func (op *storageAdapter) ObjectStorage() cloudprovider.ObjectStorageAdapter {
return op.objectStorage
}
func (op *storageAdapter) BlockStorage() cloudprovider.BlockStorageAdapter {
return op.blockStorage
}

View File

@ -17,10 +17,14 @@ limitations under the License.
package gcp
import (
"errors"
"fmt"
"strings"
"time"
uuid "github.com/satori/go.uuid"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/compute/v0.beta"
"k8s.io/apimachinery/pkg/util/wait"
@ -36,6 +40,41 @@ type blockStorageAdapter struct {
var _ cloudprovider.BlockStorageAdapter = &blockStorageAdapter{}
func NewBlockStorageAdapter(project, zone string) (cloudprovider.BlockStorageAdapter, error) {
if project == "" {
return nil, errors.New("missing project in gcp configuration in config file")
}
if zone == "" {
return nil, errors.New("missing zone in gcp configuration in config file")
}
client, err := google.DefaultClient(oauth2.NoContext, compute.ComputeScope)
if err != nil {
return nil, err
}
gce, err := compute.New(client)
if err != nil {
return nil, err
}
// validate project & zone
res, err := gce.Zones.Get(project, zone).Do()
if err != nil {
return nil, err
}
if res == nil {
return nil, fmt.Errorf("zone %q not found for project %q", project, zone)
}
return &blockStorageAdapter{
gce: gce,
project: project,
zone: zone,
}, nil
}
func (op *blockStorageAdapter) CreateVolumeFromSnapshot(snapshotID string, volumeType string, iops *int64) (volumeID string, err error) {
res, err := op.gce.Snapshots.Get(op.project, snapshotID).Do()
if err != nil {

View File

@ -20,6 +20,8 @@ import (
"io"
"strings"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
storage "google.golang.org/api/storage/v1"
"github.com/heptio/ark/pkg/cloudprovider"
@ -31,6 +33,22 @@ type objectStorageAdapter struct {
var _ cloudprovider.ObjectStorageAdapter = &objectStorageAdapter{}
func NewObjectStorageAdapter() (cloudprovider.ObjectStorageAdapter, error) {
client, err := google.DefaultClient(oauth2.NoContext, storage.DevstorageReadWriteScope)
if err != nil {
return nil, err
}
gcs, err := storage.New(client)
if err != nil {
return nil, err
}
return &objectStorageAdapter{
gcs: gcs,
}, nil
}
func (op *objectStorageAdapter) PutObject(bucket string, key string, body io.ReadSeeker) error {
obj := &storage.Object{
Name: key,

View File

@ -1,82 +0,0 @@
/*
Copyright 2017 Heptio Inc.
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 gcp
import (
"fmt"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/compute/v0.beta"
"google.golang.org/api/storage/v1"
"github.com/heptio/ark/pkg/cloudprovider"
)
type storageAdapter struct {
blockStorage *blockStorageAdapter
objectStorage *objectStorageAdapter
}
var _ cloudprovider.StorageAdapter = &storageAdapter{}
func NewStorageAdapter(project string, zone string) (cloudprovider.StorageAdapter, error) {
client, err := google.DefaultClient(oauth2.NoContext, compute.ComputeScope, storage.DevstorageReadWriteScope)
if err != nil {
return nil, err
}
gce, err := compute.New(client)
if err != nil {
return nil, err
}
// validate project & zone
res, err := gce.Zones.Get(project, zone).Do()
if err != nil {
return nil, err
}
if res == nil {
return nil, fmt.Errorf("zone %q not found for project %q", project, zone)
}
gcs, err := storage.New(client)
if err != nil {
return nil, err
}
return &storageAdapter{
objectStorage: &objectStorageAdapter{
gcs: gcs,
},
blockStorage: &blockStorageAdapter{
gce: gce,
project: project,
zone: zone,
},
}, nil
}
func (op *storageAdapter) ObjectStorage() cloudprovider.ObjectStorageAdapter {
return op.objectStorage
}
func (op *storageAdapter) BlockStorage() cloudprovider.BlockStorageAdapter {
return op.blockStorage
}

View File

@ -63,10 +63,3 @@ type BlockStorageAdapter interface {
// DeleteSnapshot deletes the specified volume snapshot.
DeleteSnapshot(snapshotID string) error
}
// StorageAdapter exposes object- and block-storage interfaces and associated methods
// for a given storage provider.
type StorageAdapter interface {
ObjectStorage() ObjectStorageAdapter
BlockStorage() BlockStorageAdapter
}

View File

@ -18,14 +18,11 @@ package server
import (
"context"
"errors"
"fmt"
"reflect"
"sync"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/golang/glog"
"github.com/spf13/cobra"
@ -242,11 +239,12 @@ func (s *server) watchConfig(config *api.Config) {
func (s *server) initBackupService(config *api.Config) error {
glog.Infof("Configuring cloud provider for backup service")
cloud, err := initCloud(config.BackupStorageProvider.CloudProviderConfig, "backupStorageProvider")
objectStorage, err := getObjectStorageProvider(config.BackupStorageProvider.CloudProviderConfig, "backupStorageProvider")
if err != nil {
return err
}
s.backupService = cloudprovider.NewBackupService(cloud.ObjectStorage())
s.backupService = cloudprovider.NewBackupService(objectStorage)
return nil
}
@ -257,102 +255,92 @@ func (s *server) initSnapshotService(config *api.Config) error {
}
glog.Infof("Configuring cloud provider for snapshot service")
cloud, err := initCloud(*config.PersistentVolumeProvider, "persistentVolumeProvider")
blockStorage, err := getBlockStorageProvider(*config.PersistentVolumeProvider, "persistentVolumeProvider")
if err != nil {
return err
}
s.snapshotService = cloudprovider.NewSnapshotService(cloud.BlockStorage())
s.snapshotService = cloudprovider.NewSnapshotService(blockStorage)
return nil
}
func initCloud(config api.CloudProviderConfig, field string) (cloudprovider.StorageAdapter, error) {
func hasOneCloudProvider(cloudConfig api.CloudProviderConfig) bool {
found := false
if cloudConfig.AWS != nil {
found = true
}
if cloudConfig.GCP != nil {
if found {
return false
}
found = true
}
if cloudConfig.Azure != nil {
if found {
return false
}
found = true
}
return found
}
func getObjectStorageProvider(cloudConfig api.CloudProviderConfig, field string) (cloudprovider.ObjectStorageAdapter, error) {
var (
cloud cloudprovider.StorageAdapter
err error
objectStorage cloudprovider.ObjectStorageAdapter
err error
)
if config.AWS != nil {
cloud, err = getAWSCloudProvider(config)
if !hasOneCloudProvider(cloudConfig) {
return nil, fmt.Errorf("you must specify exactly one of aws, gcp, or azure for %s", field)
}
if config.GCP != nil {
if cloud != nil {
return nil, fmt.Errorf("you may only specify one of aws, gcp, or azure for %s", field)
}
cloud, err = getGCPCloudProvider(config)
}
if config.Azure != nil {
if cloud != nil {
return nil, fmt.Errorf("you may only specify one of aws, gcp, or azure for %s", field)
}
cloud, err = getAzureCloudProvider(config)
switch {
case cloudConfig.AWS != nil:
objectStorage, err = arkaws.NewObjectStorageAdapter(
cloudConfig.AWS.Region,
cloudConfig.AWS.S3Url,
cloudConfig.AWS.KMSKeyID,
cloudConfig.AWS.S3ForcePathStyle)
case cloudConfig.GCP != nil:
objectStorage, err = gcp.NewObjectStorageAdapter()
case cloudConfig.Azure != nil:
objectStorage, err = azure.NewObjectStorageAdapter()
}
if err != nil {
return nil, err
}
if cloud == nil {
return nil, fmt.Errorf("you must specify one of aws, gcp, or azure for %s", field)
}
return cloud, err
return objectStorage, nil
}
func getAWSCloudProvider(cloudConfig api.CloudProviderConfig) (cloudprovider.StorageAdapter, error) {
if cloudConfig.AWS == nil {
return nil, errors.New("missing aws configuration in config file")
}
if cloudConfig.AWS.Region == "" {
return nil, errors.New("missing region in aws configuration in config file")
}
if cloudConfig.AWS.AvailabilityZone == "" {
return nil, errors.New("missing availabilityZone in aws configuration in config file")
func getBlockStorageProvider(cloudConfig api.CloudProviderConfig, field string) (cloudprovider.BlockStorageAdapter, error) {
var (
blockStorage cloudprovider.BlockStorageAdapter
err error
)
if !hasOneCloudProvider(cloudConfig) {
return nil, fmt.Errorf("you must specify exactly one of aws, gcp, or azure for %s", field)
}
awsConfig := aws.NewConfig().
WithRegion(cloudConfig.AWS.Region).
WithS3ForcePathStyle(cloudConfig.AWS.S3ForcePathStyle)
if cloudConfig.AWS.S3Url != "" {
awsConfig = awsConfig.WithEndpointResolver(
endpoints.ResolverFunc(func(service, region string, optFns ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) {
if service == endpoints.S3ServiceID {
return endpoints.ResolvedEndpoint{
URL: cloudConfig.AWS.S3Url,
}, nil
}
return endpoints.DefaultResolver().EndpointFor(service, region, optFns...)
}),
)
switch {
case cloudConfig.AWS != nil:
blockStorage, err = arkaws.NewBlockStorageAdapter(cloudConfig.AWS.Region, cloudConfig.AWS.AvailabilityZone)
case cloudConfig.GCP != nil:
blockStorage, err = gcp.NewBlockStorageAdapter(cloudConfig.GCP.Project, cloudConfig.GCP.Zone)
case cloudConfig.Azure != nil:
blockStorage, err = azure.NewBlockStorageAdapter(cloudConfig.Azure.Location, cloudConfig.Azure.APITimeout.Duration)
}
return arkaws.NewStorageAdapter(awsConfig, cloudConfig.AWS.AvailabilityZone, cloudConfig.AWS.KMSKeyID)
}
if err != nil {
return nil, err
}
func getGCPCloudProvider(cloudConfig api.CloudProviderConfig) (cloudprovider.StorageAdapter, error) {
if cloudConfig.GCP == nil {
return nil, errors.New("missing gcp configuration in config file")
}
if cloudConfig.GCP.Project == "" {
return nil, errors.New("missing project in gcp configuration in config file")
}
if cloudConfig.GCP.Zone == "" {
return nil, errors.New("missing zone in gcp configuration in config file")
}
return gcp.NewStorageAdapter(cloudConfig.GCP.Project, cloudConfig.GCP.Zone)
}
func getAzureCloudProvider(cloudConfig api.CloudProviderConfig) (cloudprovider.StorageAdapter, error) {
if cloudConfig.Azure == nil {
return nil, errors.New("missing azure configuration in config file")
}
if cloudConfig.Azure.Location == "" {
return nil, errors.New("missing location in azure configuration in config file")
}
return azure.NewStorageAdapter(cloudConfig.Azure.Location, cloudConfig.Azure.APITimeout.Duration)
return blockStorage, nil
}
func durationMin(a, b time.Duration) time.Duration {