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

chore: Adds DependsOn converters and logic #2421

Merged
merged 14 commits into from
Jun 10, 2021
Merged
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
github.com/xlab/treeprint v1.1.0
github.com/yourbasic/graph v0.0.0-20170921192928-40eb135c0b26
golang.org/x/mod v0.4.1
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
gopkg.in/ini.v1 v1.62.0
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ github.com/gobuffalo/logger v1.0.3 h1:YaXOTHNPCvkqqA7w05A4v0k2tCdpr+sgFlgINbQ6gq
github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM=
github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM=
github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI=
github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg=
github.com/gobuffalo/packr/v2 v2.8.1 h1:tkQpju6i3EtMXJ9uoF5GT6kB+LMTimDWD8Xvbz6zDVA=
github.com/gobuffalo/packr/v2 v2.8.1/go.mod h1:c/PLlOuTU+p3SybaJATW3H6lX/iK7xEz5OeMf+NnJpg=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
Expand Down Expand Up @@ -911,6 +912,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yourbasic/graph v0.0.0-20170921192928-40eb135c0b26 h1:4u7nCRnWizT8R6xOP7cGaq+Ov0oBGkKMsLWZKiwDFas=
github.com/yourbasic/graph v0.0.0-20170921192928-40eb135c0b26/go.mod h1:Rfzr+sqaDreiCaoQbFCu3sTXxeFq/9kXRuyOoSlGQHE=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/deploy/cloudformation/stack/backend_svc.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (s *BackendService) Template() (string, error) {
if err != nil {
return "", err
}
sidecars, err := convertSidecar(s.manifest.Sidecars)
sidecars, err := convertSidecar(s.manifest.Sidecars, s.manifest.ImageConfig.Image, *s.manifest.Name)
if err != nil {
return "", fmt.Errorf("convert the sidecar configuration for service %s: %w", s.name, err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/deploy/cloudformation/stack/lb_web_svc.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (s *LoadBalancedWebService) Template() (string, error) {
if err != nil {
return "", err
}
sidecars, err := convertSidecar(s.manifest.Sidecars)
sidecars, err := convertSidecar(s.manifest.Sidecars, s.manifest.ImageConfig.Image, *s.manifest.Name)
if err != nil {
return "", fmt.Errorf("convert the sidecar configuration for service %s: %w", s.name, err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (j *ScheduledJob) Template() (string, error) {
return "", err
}

sidecars, err := convertSidecar(j.manifest.Sidecars)
sidecars, err := convertSidecar(j.manifest.Sidecars, j.manifest.ImageConfig, *j.manifest.Name)
if err != nil {
return "", fmt.Errorf("convert the sidecar configuration for job %s: %w", j.name, err)
}
Expand Down
20 changes: 19 additions & 1 deletion internal/pkg/deploy/cloudformation/stack/transformers.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ var (
)

// convertSidecar converts the manifest sidecar configuration into a format parsable by the templates pkg.
func convertSidecar(s map[string]*manifest.SidecarConfig) ([]*template.SidecarOpts, error) {
func convertSidecar(s map[string]*manifest.SidecarConfig, i manifest.Image, m string) ([]*template.SidecarOpts, error) {
if s == nil {
return nil, nil
}
if err := validateNoCircularDependencies(s, i, m); err != nil {
return nil, err
}
var sidecars []*template.SidecarOpts
for name, config := range s {
port, protocol, err := parsePortMapping(config.Port)
Expand All @@ -64,6 +67,9 @@ func convertSidecar(s map[string]*manifest.SidecarConfig) ([]*template.SidecarOp
if err := validateSidecarMountPoints(config.MountPoints); err != nil {
return nil, err
}
if err := validateSidecarDependsOn(*config, name, s, m); err != nil {
return nil, err
}
mp := convertSidecarMountPoints(config.MountPoints)

sidecars = append(sidecars, &template.SidecarOpts{
Expand All @@ -77,11 +83,23 @@ func convertSidecar(s map[string]*manifest.SidecarConfig) ([]*template.SidecarOp
Variables: config.Variables,
MountPoints: mp,
DockerLabels: config.DockerLabels,
DependsOn: config.DependsOn,
})
}
return sidecars, nil
}

// convertDependsOn converts an Image DependsOn field to a template DependsOn version
func convertImageDependsOn(i *manifest.Image, s map[string]*manifest.SidecarConfig, m string) (map[string]string, error) {
if i == nil || i.DependsOn == nil {
return nil, nil
}
if err := validateImageDependsOn(*i, s, m); err != nil {
return nil, err
}
return i.DependsOn, nil
}

// Valid sidecar portMapping example: 2000/udp, or 2000 (default to be tcp).
func parsePortMapping(s *string) (port *string, protocol *string, err error) {
if s == nil {
Expand Down
188 changes: 187 additions & 1 deletion internal/pkg/deploy/cloudformation/stack/transformers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ import (

func Test_convertSidecar(t *testing.T) {
mockImage := aws.String("mockImage")
mockManifestName := "frontend"
mockMap := map[string]string{"foo": "bar"}
mockCredsParam := aws.String("mockCredsParam")
testCases := map[string]struct {
inPort string
inEssential bool
inLabels map[string]string
inDependsOn map[string]string
inImg manifest.Image

wanted *template.SidecarOpts
wantedErr error
Expand Down Expand Up @@ -60,6 +63,84 @@ func Test_convertSidecar(t *testing.T) {
Essential: aws.Bool(true),
},
},
"invalid container dependency due to circularly depending on itself": {
inPort: "2000",
inEssential: true,
inDependsOn: map[string]string{
"foo": "start",
},

wantedErr: errCircularDependency,
},
"invalid container dependency due to circularly depending on another container": {
inPort: "2000",
inEssential: true,
inDependsOn: map[string]string{
"frontend": "start",
},
inImg: manifest.Image{
DependsOn: map[string]string{
"foo": "start",
},
},
wantedErr: errCircularDependency,
},
"invalid container dependency status": {
inPort: "2000",
inEssential: true,
inDependsOn: map[string]string{
"frontend": "never",
},
wantedErr: errInvalidDependsOnStatus,
},
"invalid essential container dependency status": {
inPort: "2000",
inEssential: true,
inDependsOn: map[string]string{
"frontend": "complete",
},
wantedErr: errEssentialContainerStatus,
},
"good essential container dependencies": {
inPort: "2000",
inEssential: true,
inDependsOn: map[string]string{
"frontend": "start",
},

wanted: &template.SidecarOpts{
Name: aws.String("foo"),
Port: aws.String("2000"),
CredsParam: mockCredsParam,
Image: mockImage,
Secrets: mockMap,
Variables: mockMap,
Essential: aws.Bool(true),
DependsOn: map[string]string{
"frontend": "start",
},
},
},
"good nonessential container dependencies": {
inPort: "2000",
inEssential: false,
inDependsOn: map[string]string{
"frontend": "start",
},

wanted: &template.SidecarOpts{
Name: aws.String("foo"),
Port: aws.String("2000"),
CredsParam: mockCredsParam,
Image: mockImage,
Secrets: mockMap,
Variables: mockMap,
Essential: aws.Bool(false),
DependsOn: map[string]string{
"frontend": "start",
},
},
},
"specify essential as false": {
inPort: "2000",
inEssential: false,
Expand Down Expand Up @@ -92,9 +173,10 @@ func Test_convertSidecar(t *testing.T) {
Essential: aws.Bool(tc.inEssential),
Port: aws.String(tc.inPort),
DockerLabels: tc.inLabels,
DependsOn: tc.inDependsOn,
},
}
got, err := convertSidecar(sidecar)
got, err := convertSidecar(sidecar, tc.inImg, mockManifestName)

if tc.wantedErr != nil {
require.EqualError(t, err, tc.wantedErr.Error())
Expand Down Expand Up @@ -1155,3 +1237,107 @@ func Test_convertEphemeral(t *testing.T) {
})
}
}

func Test_convertImageDependsOn(t *testing.T) {
mockManifestName := "frontend"
testCases := map[string]struct {
inImage *manifest.Image
inSidecars map[string]*manifest.SidecarConfig

wanted map[string]string
wantedError error
}{
"no container dependencies": {
inImage: &manifest.Image{},
wanted: nil,
},
"invalid container dependency due to circular dependency on itself": {
inImage: &manifest.Image{
DependsOn: map[string]string{
"frontend": "end",
},
},
wantedError: errCircularDependency,
},
"invalid container dependency due to circular dependency on a sidecar": {
inImage: &manifest.Image{
DependsOn: map[string]string{
"sidecar": "start",
},
},
inSidecars: map[string]*manifest.SidecarConfig{
"sidecar": {
DependsOn: map[string]string{
"sidecar2": "start",
},
},
"sidecar2": {
DependsOn: map[string]string{
"frontend": "start",
},
},
},
wantedError: errCircularDependency,
},
"invalid container dependency due to status": {
inImage: &manifest.Image{
DependsOn: map[string]string{
"sidecar": "end",
},
},
inSidecars: map[string]*manifest.SidecarConfig{
"sidecar": {
Essential: aws.Bool(false),
},
},
wantedError: errInvalidDependsOnStatus,
},
"invalid implied essential container depdendency": {
inImage: &manifest.Image{
DependsOn: map[string]string{
"sidecar": "complete",
},
},
inSidecars: map[string]*manifest.SidecarConfig{
"sidecar": {},
},
wantedError: errEssentialContainerStatus,
},
"invalid set essential container depdendency": {
inImage: &manifest.Image{
DependsOn: map[string]string{
"sidecar": "complete",
},
},
inSidecars: map[string]*manifest.SidecarConfig{
"sidecar": {
Essential: aws.Bool(true),
},
},
wantedError: errEssentialContainerStatus,
},
"good essential container dependency": {
inImage: &manifest.Image{
DependsOn: map[string]string{
"sidecar": "start",
},
},
inSidecars: map[string]*manifest.SidecarConfig{
"sidecar": {},
},
wanted: map[string]string{
"sidecar": "start",
},
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
got, err := convertImageDependsOn(tc.inImage, tc.inSidecars, mockManifestName)
if tc.wantedError != nil {
require.EqualError(t, err, tc.wantedError.Error())
} else {
require.Equal(t, got, tc.wanted)
}
})
}
}
Loading