@@ -8,13 +8,72 @@ import (
88 "strings"
99
1010 "github.com/docker/cli/cli/compose/loader"
11+ "github.com/docker/cli/cli/compose/schema"
1112 composeTypes "github.com/docker/cli/cli/compose/types"
1213 composetypes "github.com/docker/cli/cli/compose/types"
1314 "github.com/docker/cli/kubernetes/compose/v1beta1"
1415 "github.com/docker/cli/kubernetes/compose/v1beta2"
16+ "github.com/pkg/errors"
17+ yaml "gopkg.in/yaml.v2"
1518 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1619)
1720
21+ // NewStackConverter returns a converter from types.Config (compose) to the specified
22+ // stack version or error out if the version is not supported or existent.
23+ func NewStackConverter (version string ) (StackConverter , error ) {
24+ switch version {
25+ case "v1beta1" :
26+ return stackV1Beta1Converter {}, nil
27+ case "v1beta2" :
28+ return stackV1Beta2Converter {}, nil
29+ default :
30+ return nil , errors .Errorf ("stack version %s unsupported" , version )
31+ }
32+ }
33+
34+ // StackConverter converts a compose types.Config to a Stack
35+ type StackConverter interface {
36+ FromCompose (stderr io.Writer , name string , cfg * composetypes.Config ) (Stack , error )
37+ }
38+
39+ type stackV1Beta1Converter struct {}
40+
41+ func (s stackV1Beta1Converter ) FromCompose (stderr io.Writer , name string , cfg * composetypes.Config ) (Stack , error ) {
42+ cfg .Version = v1beta1 .MaxComposeVersion
43+ st , err := fromCompose (stderr , name , cfg )
44+ if err != nil {
45+ return Stack {}, err
46+ }
47+ res , err := yaml .Marshal (cfg )
48+ if err != nil {
49+ return Stack {}, err
50+ }
51+ // reload the result to check that it produced a valid 3.5 compose file
52+ resparsedConfig , err := loader .ParseYAML (res )
53+ if err != nil {
54+ return Stack {}, err
55+ }
56+ if err = schema .Validate (resparsedConfig , v1beta1 .MaxComposeVersion ); err != nil {
57+ return Stack {}, errors .Wrapf (err , "the compose yaml file is invalid with v%s" , v1beta1 .MaxComposeVersion )
58+ }
59+
60+ st .ComposeFile = string (res )
61+ return st , nil
62+ }
63+
64+ type stackV1Beta2Converter struct {}
65+
66+ func (s stackV1Beta2Converter ) FromCompose (stderr io.Writer , name string , cfg * composetypes.Config ) (Stack , error ) {
67+ return fromCompose (stderr , name , cfg )
68+ }
69+
70+ func fromCompose (stderr io.Writer , name string , cfg * composetypes.Config ) (Stack , error ) {
71+ return Stack {
72+ Name : name ,
73+ Spec : fromComposeConfig (stderr , cfg ),
74+ }, nil
75+ }
76+
1877func loadStackData (composefile string ) (* composetypes.Config , error ) {
1978 parsed , err := loader .ParseYAML ([]byte (composefile ))
2079 if err != nil {
@@ -30,44 +89,44 @@ func loadStackData(composefile string) (*composetypes.Config, error) {
3089}
3190
3291// Conversions from internal stack to different stack compose component versions.
33- func stackFromV1beta1 (in * v1beta1.Stack ) (stack , error ) {
92+ func stackFromV1beta1 (in * v1beta1.Stack ) (Stack , error ) {
3493 cfg , err := loadStackData (in .Spec .ComposeFile )
3594 if err != nil {
36- return stack {}, err
95+ return Stack {}, err
3796 }
38- return stack {
39- name : in .ObjectMeta .Name ,
40- namespace : in .ObjectMeta .Namespace ,
41- composeFile : in .Spec .ComposeFile ,
42- spec : fromComposeConfig (ioutil .Discard , cfg ),
97+ return Stack {
98+ Name : in .ObjectMeta .Name ,
99+ Namespace : in .ObjectMeta .Namespace ,
100+ ComposeFile : in .Spec .ComposeFile ,
101+ Spec : fromComposeConfig (ioutil .Discard , cfg ),
43102 }, nil
44103}
45104
46- func stackToV1beta1 (s stack ) * v1beta1.Stack {
105+ func stackToV1beta1 (s Stack ) * v1beta1.Stack {
47106 return & v1beta1.Stack {
48107 ObjectMeta : metav1.ObjectMeta {
49- Name : s .name ,
108+ Name : s .Name ,
50109 },
51110 Spec : v1beta1.StackSpec {
52- ComposeFile : s .composeFile ,
111+ ComposeFile : s .ComposeFile ,
53112 },
54113 }
55114}
56115
57- func stackFromV1beta2 (in * v1beta2.Stack ) stack {
58- return stack {
59- name : in .ObjectMeta .Name ,
60- namespace : in .ObjectMeta .Namespace ,
61- spec : in .Spec ,
116+ func stackFromV1beta2 (in * v1beta2.Stack ) Stack {
117+ return Stack {
118+ Name : in .ObjectMeta .Name ,
119+ Namespace : in .ObjectMeta .Namespace ,
120+ Spec : in .Spec ,
62121 }
63122}
64123
65- func stackToV1beta2 (s stack ) * v1beta2.Stack {
124+ func stackToV1beta2 (s Stack ) * v1beta2.Stack {
66125 return & v1beta2.Stack {
67126 ObjectMeta : metav1.ObjectMeta {
68- Name : s .name ,
127+ Name : s .Name ,
69128 },
70- Spec : s .spec ,
129+ Spec : s .Spec ,
71130 }
72131}
73132
0 commit comments