Added tests on ACI volume conversion, mock storageLogin required to get storage account keys

Signed-off-by: Guillaume Tardif <guillaume.tardif@docker.com>
This commit is contained in:
Guillaume Tardif 2020-09-22 11:45:02 +02:00
parent 772493d70d
commit 0092de6df1
7 changed files with 149 additions and 39 deletions

View File

@ -88,13 +88,11 @@ func getCloudService() (cloud.Service, error) {
} }
func getAciAPIService(aciCtx store.AciContext) *aciAPIService { func getAciAPIService(aciCtx store.AciContext) *aciAPIService {
containerService := newContainerService(aciCtx)
composeService := newComposeService(aciCtx)
return &aciAPIService{ return &aciAPIService{
aciContainerService: &aciContainerService{ aciContainerService: &containerService,
ctx: aciCtx, aciComposeService: &composeService,
},
aciComposeService: &aciComposeService{
ctx: aciCtx,
},
aciVolumeService: &aciVolumeService{ aciVolumeService: &aciVolumeService{
aciContext: aciCtx, aciContext: aciCtx,
}, },

View File

@ -34,11 +34,19 @@ import (
type aciComposeService struct { type aciComposeService struct {
ctx store.AciContext ctx store.AciContext
storageLogin login.StorageLoginImpl
}
func newComposeService(ctx store.AciContext) aciComposeService {
return aciComposeService{
ctx: ctx,
storageLogin: login.StorageLoginImpl{AciContext: ctx},
}
} }
func (cs *aciComposeService) Up(ctx context.Context, project *types.Project) error { func (cs *aciComposeService) Up(ctx context.Context, project *types.Project) error {
logrus.Debugf("Up on project with name %q", project.Name) logrus.Debugf("Up on project with name %q", project.Name)
groupDefinition, err := convert.ToContainerGroup(ctx, cs.ctx, *project) groupDefinition, err := convert.ToContainerGroup(ctx, cs.ctx, *project, cs.storageLogin)
addTag(&groupDefinition, composeContainerTag) addTag(&groupDefinition, composeContainerTag)
if err != nil { if err != nil {

View File

@ -38,6 +38,14 @@ import (
type aciContainerService struct { type aciContainerService struct {
ctx store.AciContext ctx store.AciContext
storageLogin login.StorageLoginImpl
}
func newContainerService(ctx store.AciContext) aciContainerService {
return aciContainerService{
ctx: ctx,
storageLogin: login.StorageLoginImpl{AciContext: ctx},
}
} }
func (cs *aciContainerService) List(ctx context.Context, all bool) ([]containers.Container, error) { func (cs *aciContainerService) List(ctx context.Context, all bool) ([]containers.Container, error) {
@ -73,7 +81,7 @@ func (cs *aciContainerService) Run(ctx context.Context, r containers.ContainerCo
} }
logrus.Debugf("Running container %q with name %q", r.Image, r.ID) logrus.Debugf("Running container %q with name %q", r.Image, r.ID)
groupDefinition, err := convert.ToContainerGroup(ctx, cs.ctx, project) groupDefinition, err := convert.ToContainerGroup(ctx, cs.ctx, project, cs.storageLogin)
if err != nil { if err != nil {
return err return err
} }

View File

@ -26,17 +26,16 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/utils/formatter"
"github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance" "github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"
"github.com/Azure/go-autorest/autorest/to" "github.com/Azure/go-autorest/autorest/to"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/docker/compose-cli/aci/login" "github.com/docker/compose-cli/aci/login"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/api/containers" "github.com/docker/compose-cli/api/containers"
"github.com/docker/compose-cli/context/store" "github.com/docker/compose-cli/context/store"
"github.com/docker/compose-cli/utils/formatter"
) )
const ( const (
@ -54,12 +53,9 @@ const (
) )
// ToContainerGroup converts a compose project into a ACI container group // ToContainerGroup converts a compose project into a ACI container group
func ToContainerGroup(ctx context.Context, aciContext store.AciContext, p types.Project) (containerinstance.ContainerGroup, error) { func ToContainerGroup(ctx context.Context, aciContext store.AciContext, p types.Project, storageHelper login.StorageLogin) (containerinstance.ContainerGroup, error) {
project := projectAciHelper(p) project := projectAciHelper(p)
containerGroupName := strings.ToLower(project.Name) containerGroupName := strings.ToLower(project.Name)
storageHelper := login.StorageLogin{
AciContext: aciContext,
}
volumesCache, volumesSlice, err := project.getAciFileVolumes(ctx, storageHelper) volumesCache, volumesSlice, err := project.getAciFileVolumes(ctx, storageHelper)
if err != nil { if err != nil {
return containerinstance.ContainerGroup{}, err return containerinstance.ContainerGroup{}, err

View File

@ -21,29 +21,33 @@ import (
"os" "os"
"testing" "testing"
"github.com/docker/compose-cli/api/compose" "github.com/stretchr/testify/mock"
"github.com/Azure/azure-sdk-for-go/profiles/latest/containerinstance/mgmt/containerinstance" "github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"
"github.com/Azure/go-autorest/autorest/to" "github.com/Azure/go-autorest/autorest/to"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/api/containers" "github.com/docker/compose-cli/api/containers"
"github.com/docker/compose-cli/context/store" "github.com/docker/compose-cli/context/store"
) )
var convertCtx = store.AciContext{ var (
convertCtx = store.AciContext{
SubscriptionID: "subID", SubscriptionID: "subID",
ResourceGroup: "rg", ResourceGroup: "rg",
Location: "eu", Location: "eu",
} }
mockStorageHelper = &mockStorageLogin{}
)
func TestProjectName(t *testing.T) { func TestProjectName(t *testing.T) {
project := types.Project{ project := types.Project{
Name: "TEST", Name: "TEST",
} }
containerGroup, err := ToContainerGroup(context.TODO(), convertCtx, project) containerGroup, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, *containerGroup.Name, "test") assert.Equal(t, *containerGroup.Name, "test")
} }
@ -157,7 +161,7 @@ func TestComposeContainerGroupToContainerWithDnsSideCarSide(t *testing.T) {
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
assert.Assert(t, is.Len(*group.Containers, 3)) assert.Assert(t, is.Len(*group.Containers, 3))
@ -182,7 +186,7 @@ func TestComposeSingleContainerGroupToContainerNoDnsSideCarSide(t *testing.T) {
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
assert.Assert(t, is.Len(*group.Containers, 1)) assert.Assert(t, is.Len(*group.Containers, 1))
@ -190,6 +194,96 @@ func TestComposeSingleContainerGroupToContainerNoDnsSideCarSide(t *testing.T) {
assert.Equal(t, *(*group.Containers)[0].Image, "image1") assert.Equal(t, *(*group.Containers)[0].Image, "image1")
} }
func TestComposeVolumes(t *testing.T) {
ctx := context.TODO()
accountName := "myAccount"
mockStorageHelper.On("GetAzureStorageAccountKey", ctx, accountName).Return("123456", nil)
project := types.Project{
Services: []types.ServiceConfig{
{
Name: "service1",
Image: "image1",
},
},
Volumes: types.Volumes{
"vol1": types.VolumeConfig{
Driver: "azure_file",
DriverOpts: map[string]string{
"share_name": "myFileshare",
"storage_account_name": accountName,
},
},
},
}
group, err := ToContainerGroup(ctx, convertCtx, project, mockStorageHelper)
assert.NilError(t, err)
assert.Assert(t, is.Len(*group.Containers, 1))
assert.Equal(t, *(*group.Containers)[0].Name, "service1")
expectedGroupVolume := containerinstance.Volume{
Name: to.StringPtr("vol1"),
AzureFile: &containerinstance.AzureFileVolume{
ShareName: to.StringPtr("myFileshare"),
StorageAccountName: &accountName,
StorageAccountKey: to.StringPtr("123456"),
ReadOnly: to.BoolPtr(false),
},
}
assert.Equal(t, len(*group.Volumes), 1)
assert.DeepEqual(t, (*group.Volumes)[0], expectedGroupVolume)
}
func TestComposeVolumesRO(t *testing.T) {
ctx := context.TODO()
accountName := "myAccount"
mockStorageHelper.On("GetAzureStorageAccountKey", ctx, accountName).Return("123456", nil)
project := types.Project{
Services: []types.ServiceConfig{
{
Name: "service1",
Image: "image1",
},
},
Volumes: types.Volumes{
"vol1": types.VolumeConfig{
Driver: "azure_file",
DriverOpts: map[string]string{
"share_name": "myFileshare",
"storage_account_name": accountName,
"read_only": "true",
},
},
},
}
group, err := ToContainerGroup(ctx, convertCtx, project, mockStorageHelper)
assert.NilError(t, err)
assert.Assert(t, is.Len(*group.Containers, 1))
assert.Equal(t, *(*group.Containers)[0].Name, "service1")
expectedGroupVolume := containerinstance.Volume{
Name: to.StringPtr("vol1"),
AzureFile: &containerinstance.AzureFileVolume{
ShareName: to.StringPtr("myFileshare"),
StorageAccountName: &accountName,
StorageAccountKey: to.StringPtr("123456"),
ReadOnly: to.BoolPtr(true),
},
}
assert.Equal(t, len(*group.Volumes), 1)
assert.DeepEqual(t, (*group.Volumes)[0], expectedGroupVolume)
}
type mockStorageLogin struct {
mock.Mock
}
func (s *mockStorageLogin) GetAzureStorageAccountKey(ctx context.Context, accountName string) (string, error) {
args := s.Called(ctx, accountName)
return args.String(0), args.Error(1)
}
func TestComposeSingleContainerRestartPolicy(t *testing.T) { func TestComposeSingleContainerRestartPolicy(t *testing.T) {
project := types.Project{ project := types.Project{
Services: []types.ServiceConfig{ Services: []types.ServiceConfig{
@ -205,7 +299,7 @@ func TestComposeSingleContainerRestartPolicy(t *testing.T) {
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
assert.Assert(t, is.Len(*group.Containers, 1)) assert.Assert(t, is.Len(*group.Containers, 1))
@ -237,7 +331,7 @@ func TestComposeMultiContainerRestartPolicy(t *testing.T) {
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
assert.Assert(t, is.Len(*group.Containers, 3)) assert.Assert(t, is.Len(*group.Containers, 3))
@ -271,7 +365,7 @@ func TestComposeInconsistentMultiContainerRestartPolicy(t *testing.T) {
}, },
} }
_, err := ToContainerGroup(context.TODO(), convertCtx, project) _, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.Error(t, err, "ACI integration does not support specifying different restart policies on containers in the same compose application") assert.Error(t, err, "ACI integration does not support specifying different restart policies on containers in the same compose application")
} }
@ -288,7 +382,7 @@ func TestLabelsErrorMessage(t *testing.T) {
}, },
} }
_, err := ToContainerGroup(context.TODO(), convertCtx, project) _, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.Error(t, err, "ACI integration does not support labels in compose applications") assert.Error(t, err, "ACI integration does not support labels in compose applications")
} }
@ -302,7 +396,7 @@ func TestComposeSingleContainerGroupToContainerDefaultRestartPolicy(t *testing.T
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
assert.Assert(t, is.Len(*group.Containers, 1)) assert.Assert(t, is.Len(*group.Containers, 1))
@ -336,7 +430,7 @@ func TestComposeContainerGroupToContainerMultiplePorts(t *testing.T) {
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
assert.Assert(t, is.Len(*group.Containers, 3)) assert.Assert(t, is.Len(*group.Containers, 3))
@ -375,7 +469,7 @@ func TestComposeContainerGroupToContainerResourceLimits(t *testing.T) {
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
limits := *((*group.Containers)[0]).Resources.Limits limits := *((*group.Containers)[0]).Resources.Limits
@ -401,7 +495,7 @@ func TestComposeContainerGroupToContainerResourceLimitsDefaults(t *testing.T) {
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
limits := *((*group.Containers)[0]).Resources.Limits limits := *((*group.Containers)[0]).Resources.Limits
@ -425,7 +519,7 @@ func TestComposeContainerGroupToContainerenvVar(t *testing.T) {
}, },
} }
group, err := ToContainerGroup(context.TODO(), convertCtx, project) group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
assert.NilError(t, err) assert.NilError(t, err)
envVars := *((*group.Containers)[0]).EnvironmentVariables envVars := *((*group.Containers)[0]).EnvironmentVariables

View File

@ -26,12 +26,18 @@ import (
) )
// StorageLogin helper for Azure Storage Login // StorageLogin helper for Azure Storage Login
type StorageLogin struct { type StorageLogin interface {
// GetAzureStorageAccountKey retrieves the storage account ket from the current azure login
GetAzureStorageAccountKey(ctx context.Context, accountName string) (string, error)
}
// StorageLoginImpl implementation of StorageLogin
type StorageLoginImpl struct {
AciContext store.AciContext AciContext store.AciContext
} }
// GetAzureStorageAccountKey retrieves the storage account ket from the current azure login // GetAzureStorageAccountKey retrieves the storage account ket from the current azure login
func (helper StorageLogin) GetAzureStorageAccountKey(ctx context.Context, accountName string) (string, error) { func (helper StorageLoginImpl) GetAzureStorageAccountKey(ctx context.Context, accountName string) (string, error) {
client, err := NewStorageAccountsClient(helper.AciContext.SubscriptionID) client, err := NewStorageAccountsClient(helper.AciContext.SubscriptionID)
if err != nil { if err != nil {
return "", err return "", err

View File

@ -197,7 +197,7 @@ func TestContainerRunVolume(t *testing.T) {
}) })
t.Run("upload file", func(t *testing.T) { t.Run("upload file", func(t *testing.T) {
storageLogin := login.StorageLogin{AciContext: aciContext} storageLogin := login.StorageLoginImpl{AciContext: aciContext}
key, err := storageLogin.GetAzureStorageAccountKey(context.TODO(), accountName) key, err := storageLogin.GetAzureStorageAccountKey(context.TODO(), accountName)
assert.NilError(t, err) assert.NilError(t, err)