From e0f20fd86ab734768b8f9f813fa30208bb7ae248 Mon Sep 17 00:00:00 2001 From: Simon Ferquel Date: Fri, 12 Apr 2019 15:18:45 +0200 Subject: [PATCH] Regroup all kubernetes extra-fields under x-kubernetes This regroup all Kubernetes extra fields for compose-on-kubernetes v1alpha3 in a single x-kubernetes object. Also use the same naming scheme as cap_add etc. for fiels inside this object. Signed-off-by: Simon Ferquel --- cli/command/stack/kubernetes/convert.go | 97 ++++++++----------- cli/command/stack/kubernetes/convert_test.go | 20 ++-- .../testdata/compose-with-pull-policy.yml | 3 +- .../testdata/compose-with-pull-secret.yml | 3 +- 4 files changed, 58 insertions(+), 65 deletions(-) diff --git a/cli/command/stack/kubernetes/convert.go b/cli/command/stack/kubernetes/convert.go index c1e066b2c3..e42705cbb5 100644 --- a/cli/command/stack/kubernetes/convert.go +++ b/cli/command/stack/kubernetes/convert.go @@ -15,6 +15,7 @@ import ( "github.com/docker/compose-on-kubernetes/api/compose/v1beta1" "github.com/docker/compose-on-kubernetes/api/compose/v1beta2" "github.com/docker/go-connections/nat" + "github.com/mitchellh/mapstructure" "github.com/pkg/errors" yaml "gopkg.in/yaml.v2" v1 "k8s.io/api/core/v1" @@ -22,12 +23,8 @@ import ( ) const ( - // pullSecretExtraField is an extra field on ServiceConfigs usable to reference a pull secret - pullSecretExtraField = "x-pull-secret" - // pullPolicyExtraField is an extra field on ServiceConfigs usable to specify a pull policy - pullPolicyExtraField = "x-pull-policy" - // internalServiceTypeExtraField is an extra field on ServiceConfigs to explicitly specify the kind of service to setup for intra-stack networking - internalServiceTypeExtraField = "x-internal-service-type" + // kubernatesExtraField is an extra field on ServiceConfigs containing kubernetes-specific extensions to compose format + kubernatesExtraField = "x-kubernetes" ) // NewStackConverter returns a converter from types.Config (compose) to the specified @@ -249,10 +246,8 @@ func fromComposeConfigs(s map[string]composeTypes.ConfigObjConfig) map[string]la func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities composeCapabilities) (latest.ServiceConfig, error) { var ( - userID *int64 - pullSecret string - pullPolicy string - err error + userID *int64 + err error ) if s.User != "" { numerical, err := strconv.Atoi(s.User) @@ -261,23 +256,18 @@ func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities compose userID = &unixUserID } } - pullSecret, err = resolveServiceExtra(s, pullSecretExtraField) + kubeExtra, err := resolveServiceExtra(s) if err != nil { return latest.ServiceConfig{}, err } - pullPolicy, err = resolveServiceExtra(s, pullPolicyExtraField) - if err != nil { - return latest.ServiceConfig{}, err + if kubeExtra.PullSecret != "" && !capabilities.hasPullSecrets { + return latest.ServiceConfig{}, errors.Errorf(`stack API version %s does not support pull secrets (field "x-kubernetes.pull_secret"), please use version v1alpha3 or higher`, capabilities.apiVersion) + } + if kubeExtra.PullPolicy != "" && !capabilities.hasPullPolicies { + return latest.ServiceConfig{}, errors.Errorf(`stack API version %s does not support pull policies (field "x-kubernetes.pull_policy"), please use version v1alpha3 or higher`, capabilities.apiVersion) } - if pullSecret != "" && !capabilities.hasPullSecrets { - return latest.ServiceConfig{}, errors.Errorf("stack API version %s does not support pull secrets (field %q), please use version v1alpha3 or higher", capabilities.apiVersion, pullSecretExtraField) - } - if pullPolicy != "" && !capabilities.hasPullPolicies { - return latest.ServiceConfig{}, errors.Errorf("stack API version %s does not support pull policies (field %q), please use version v1alpha3 or higher", capabilities.apiVersion, pullPolicyExtraField) - } - - internalServiceType, internalPorts, err := setupIntraStackNetworking(s, capabilities) + internalPorts, err := setupIntraStackNetworking(s, kubeExtra, capabilities) if err != nil { return latest.ServiceConfig{}, err } @@ -317,48 +307,41 @@ func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities compose User: userID, Volumes: fromComposeServiceVolumeConfig(s.Volumes), WorkingDir: s.WorkingDir, - PullSecret: pullSecret, - PullPolicy: pullPolicy, - InternalServiceType: internalServiceType, + PullSecret: kubeExtra.PullSecret, + PullPolicy: kubeExtra.PullPolicy, + InternalServiceType: kubeExtra.InternalServiceType, InternalPorts: internalPorts, }, nil } -func setupIntraStackNetworking(s composeTypes.ServiceConfig, capabilities composeCapabilities) (latest.InternalServiceType, []latest.InternalPort, error) { - internalServiceTypeRaw, err := resolveServiceExtra(s, internalServiceTypeExtraField) - if err != nil { - return latest.InternalServiceTypeAuto, nil, err - } - if internalServiceTypeRaw != "" && !capabilities.hasIntraStackLoadBalancing { - return latest.InternalServiceTypeAuto, nil, - errors.Errorf("stack API version %s does not support intra-stack load balancing (field %q), please use version v1alpha3 or higher", capabilities.apiVersion, internalServiceTypeExtraField) +func setupIntraStackNetworking(s composeTypes.ServiceConfig, kubeExtra kubernetesExtra, capabilities composeCapabilities) ([]latest.InternalPort, error) { + if kubeExtra.InternalServiceType != latest.InternalServiceTypeAuto && !capabilities.hasIntraStackLoadBalancing { + return nil, + errors.Errorf(`stack API version %s does not support intra-stack load balancing (field "x-kubernetes.internal_service_type"), please use version v1alpha3 or higher`, + capabilities.apiVersion) } if !capabilities.hasIntraStackLoadBalancing { - return latest.InternalServiceTypeAuto, nil, nil + return nil, nil } - internalServiceType, err := validateInternalServiceType(internalServiceTypeRaw) - if err != nil { - return latest.InternalServiceTypeAuto, nil, err + if err := validateInternalServiceType(kubeExtra.InternalServiceType); err != nil { + return nil, err } internalPorts, err := toInternalPorts(s.Expose) if err != nil { - return latest.InternalServiceTypeAuto, nil, err + return nil, err } - return internalServiceType, internalPorts, nil + return internalPorts, nil } -func validateInternalServiceType(raw string) (latest.InternalServiceType, error) { - internalServiceType := latest.InternalServiceType(raw) +func validateInternalServiceType(internalServiceType latest.InternalServiceType) error { switch internalServiceType { case latest.InternalServiceTypeAuto, latest.InternalServiceTypeClusterIP, latest.InternalServiceTypeHeadless: default: - return latest.InternalServiceTypeAuto, - errors.Errorf("invalid value %q for field %q, valid values are %q or %q", raw, - internalServiceTypeExtraField, - latest.InternalServiceTypeClusterIP, - latest.InternalServiceTypeHeadless) + return errors.Errorf(`invalid value %q for field "x-kubernetes.internal_service_type", valid values are %q or %q`, internalServiceType, + latest.InternalServiceTypeClusterIP, + latest.InternalServiceTypeHeadless) } - return internalServiceType, nil + return nil } func toInternalPorts(expose []string) ([]latest.InternalPort, error) { @@ -385,15 +368,15 @@ func toInternalPorts(expose []string) ([]latest.InternalPort, error) { return internalPorts, nil } -func resolveServiceExtra(s composeTypes.ServiceConfig, field string) (string, error) { - if iface, ok := s.Extras[field]; ok { - value, ok := iface.(string) - if !ok { - return "", errors.Errorf("field %q: value %v type is %T, should be a string", field, iface, iface) +func resolveServiceExtra(s composeTypes.ServiceConfig) (kubernetesExtra, error) { + if iface, ok := s.Extras[kubernatesExtraField]; ok { + var result kubernetesExtra + if err := mapstructure.Decode(iface, &result); err != nil { + return kubernetesExtra{}, err } - return value, nil + return result, nil } - return "", nil + return kubernetesExtra{}, nil } func fromComposePorts(ports []composeTypes.ServicePortConfig) []latest.ServicePortConfig { @@ -576,3 +559,9 @@ type composeCapabilities struct { hasPullPolicies bool hasIntraStackLoadBalancing bool } + +type kubernetesExtra struct { + PullSecret string `mapstructure:"pull_secret"` + PullPolicy string `mapstructure:"pull_policy"` + InternalServiceType latest.InternalServiceType `mapstructure:"internal_service_type"` +} diff --git a/cli/command/stack/kubernetes/convert_test.go b/cli/command/stack/kubernetes/convert_test.go index 14634eaa38..1cdf4f276b 100644 --- a/cli/command/stack/kubernetes/convert_test.go +++ b/cli/command/stack/kubernetes/convert_test.go @@ -13,7 +13,7 @@ import ( "github.com/docker/compose-on-kubernetes/api/compose/v1beta2" "gotest.tools/assert" is "gotest.tools/assert/cmp" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -189,8 +189,8 @@ func TestHandlePullSecret(t *testing.T) { version string err string }{ - {version: "v1beta1", err: `stack API version v1beta1 does not support pull secrets (field "x-pull-secret"), please use version v1alpha3 or higher`}, - {version: "v1beta2", err: `stack API version v1beta2 does not support pull secrets (field "x-pull-secret"), please use version v1alpha3 or higher`}, + {version: "v1beta1", err: `stack API version v1beta1 does not support pull secrets (field "x-kubernetes.pull_secret"), please use version v1alpha3 or higher`}, + {version: "v1beta2", err: `stack API version v1beta2 does not support pull secrets (field "x-kubernetes.pull_secret"), please use version v1alpha3 or higher`}, {version: "v1alpha3"}, } @@ -216,8 +216,8 @@ func TestHandlePullPolicy(t *testing.T) { version string err string }{ - {version: "v1beta1", err: `stack API version v1beta1 does not support pull policies (field "x-pull-policy"), please use version v1alpha3 or higher`}, - {version: "v1beta2", err: `stack API version v1beta2 does not support pull policies (field "x-pull-policy"), please use version v1alpha3 or higher`}, + {version: "v1beta1", err: `stack API version v1beta1 does not support pull policies (field "x-kubernetes.pull_policy"), please use version v1alpha3 or higher`}, + {version: "v1beta2", err: `stack API version v1beta2 does not support pull policies (field "x-kubernetes.pull_policy"), please use version v1alpha3 or higher`}, {version: "v1alpha3"}, } @@ -249,13 +249,13 @@ func TestHandleInternalServiceType(t *testing.T) { name: "v1beta1", value: "ClusterIP", caps: v1beta1Capabilities, - err: `stack API version v1beta1 does not support intra-stack load balancing (field "x-internal-service-type"), please use version v1alpha3 or higher`, + err: `stack API version v1beta1 does not support intra-stack load balancing (field "x-kubernetes.internal_service_type"), please use version v1alpha3 or higher`, }, { name: "v1beta2", value: "ClusterIP", caps: v1beta2Capabilities, - err: `stack API version v1beta2 does not support intra-stack load balancing (field "x-internal-service-type"), please use version v1alpha3 or higher`, + err: `stack API version v1beta2 does not support intra-stack load balancing (field "x-kubernetes.internal_service_type"), please use version v1alpha3 or higher`, }, { name: "v1alpha3", @@ -267,7 +267,7 @@ func TestHandleInternalServiceType(t *testing.T) { name: "v1alpha3-invalid", value: "invalid", caps: v1alpha3Capabilities, - err: `invalid value "invalid" for field "x-internal-service-type", valid values are "ClusterIP" or "Headless"`, + err: `invalid value "invalid" for field "x-kubernetes.internal_service_type", valid values are "ClusterIP" or "Headless"`, }, } for _, c := range cases { @@ -276,7 +276,9 @@ func TestHandleInternalServiceType(t *testing.T) { Name: "test", Image: "test", Extras: map[string]interface{}{ - internalServiceTypeExtraField: c.value, + "x-kubernetes": map[string]interface{}{ + "internal_service_type": c.value, + }, }, }, c.caps) if c.err == "" { diff --git a/cli/command/stack/kubernetes/testdata/compose-with-pull-policy.yml b/cli/command/stack/kubernetes/testdata/compose-with-pull-policy.yml index 328416ee1c..471988f574 100644 --- a/cli/command/stack/kubernetes/testdata/compose-with-pull-policy.yml +++ b/cli/command/stack/kubernetes/testdata/compose-with-pull-policy.yml @@ -2,4 +2,5 @@ version: "3.7" services: test: image: "some-image" - x-pull-policy: "Never" \ No newline at end of file + x-kubernetes: + pull_policy: "Never" \ No newline at end of file diff --git a/cli/command/stack/kubernetes/testdata/compose-with-pull-secret.yml b/cli/command/stack/kubernetes/testdata/compose-with-pull-secret.yml index 8510f5c541..8c2653787d 100644 --- a/cli/command/stack/kubernetes/testdata/compose-with-pull-secret.yml +++ b/cli/command/stack/kubernetes/testdata/compose-with-pull-secret.yml @@ -2,4 +2,5 @@ version: "3.7" services: test: image: "some-private-image" - x-pull-secret: "some-secret" \ No newline at end of file + x-kubernetes: + pull_secret: "some-secret" \ No newline at end of file