mirror of https://github.com/docker/cli.git
Merge pull request #1823 from simonferquel/refactor-kubernetes-extras
Regroup all kubernetes extra-fields under x-kubernetes
This commit is contained in:
commit
d043ab5993
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
"github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||||
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
@ -22,12 +23,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// pullSecretExtraField is an extra field on ServiceConfigs usable to reference a pull secret
|
// kubernatesExtraField is an extra field on ServiceConfigs containing kubernetes-specific extensions to compose format
|
||||||
pullSecretExtraField = "x-pull-secret"
|
kubernatesExtraField = "x-kubernetes"
|
||||||
// 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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewStackConverter returns a converter from types.Config (compose) to the specified
|
// NewStackConverter returns a converter from types.Config (compose) to the specified
|
||||||
|
@ -250,8 +247,6 @@ func fromComposeConfigs(s map[string]composeTypes.ConfigObjConfig) map[string]la
|
||||||
func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities composeCapabilities) (latest.ServiceConfig, error) {
|
func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities composeCapabilities) (latest.ServiceConfig, error) {
|
||||||
var (
|
var (
|
||||||
userID *int64
|
userID *int64
|
||||||
pullSecret string
|
|
||||||
pullPolicy string
|
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if s.User != "" {
|
if s.User != "" {
|
||||||
|
@ -261,23 +256,18 @@ func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities compose
|
||||||
userID = &unixUserID
|
userID = &unixUserID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pullSecret, err = resolveServiceExtra(s, pullSecretExtraField)
|
kubeExtra, err := resolveServiceExtra(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return latest.ServiceConfig{}, err
|
return latest.ServiceConfig{}, err
|
||||||
}
|
}
|
||||||
pullPolicy, err = resolveServiceExtra(s, pullPolicyExtraField)
|
if kubeExtra.PullSecret != "" && !capabilities.hasPullSecrets {
|
||||||
if err != nil {
|
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)
|
||||||
return latest.ServiceConfig{}, err
|
}
|
||||||
|
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 {
|
internalPorts, err := setupIntraStackNetworking(s, kubeExtra, capabilities)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return latest.ServiceConfig{}, err
|
return latest.ServiceConfig{}, err
|
||||||
}
|
}
|
||||||
|
@ -317,48 +307,41 @@ func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities compose
|
||||||
User: userID,
|
User: userID,
|
||||||
Volumes: fromComposeServiceVolumeConfig(s.Volumes),
|
Volumes: fromComposeServiceVolumeConfig(s.Volumes),
|
||||||
WorkingDir: s.WorkingDir,
|
WorkingDir: s.WorkingDir,
|
||||||
PullSecret: pullSecret,
|
PullSecret: kubeExtra.PullSecret,
|
||||||
PullPolicy: pullPolicy,
|
PullPolicy: kubeExtra.PullPolicy,
|
||||||
InternalServiceType: internalServiceType,
|
InternalServiceType: kubeExtra.InternalServiceType,
|
||||||
InternalPorts: internalPorts,
|
InternalPorts: internalPorts,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupIntraStackNetworking(s composeTypes.ServiceConfig, capabilities composeCapabilities) (latest.InternalServiceType, []latest.InternalPort, error) {
|
func setupIntraStackNetworking(s composeTypes.ServiceConfig, kubeExtra kubernetesExtra, capabilities composeCapabilities) ([]latest.InternalPort, error) {
|
||||||
internalServiceTypeRaw, err := resolveServiceExtra(s, internalServiceTypeExtraField)
|
if kubeExtra.InternalServiceType != latest.InternalServiceTypeAuto && !capabilities.hasIntraStackLoadBalancing {
|
||||||
if err != nil {
|
return nil,
|
||||||
return latest.InternalServiceTypeAuto, nil, err
|
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 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)
|
|
||||||
}
|
}
|
||||||
if !capabilities.hasIntraStackLoadBalancing {
|
if !capabilities.hasIntraStackLoadBalancing {
|
||||||
return latest.InternalServiceTypeAuto, nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
internalServiceType, err := validateInternalServiceType(internalServiceTypeRaw)
|
if err := validateInternalServiceType(kubeExtra.InternalServiceType); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return latest.InternalServiceTypeAuto, nil, err
|
|
||||||
}
|
}
|
||||||
internalPorts, err := toInternalPorts(s.Expose)
|
internalPorts, err := toInternalPorts(s.Expose)
|
||||||
if err != nil {
|
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) {
|
func validateInternalServiceType(internalServiceType latest.InternalServiceType) error {
|
||||||
internalServiceType := latest.InternalServiceType(raw)
|
|
||||||
switch internalServiceType {
|
switch internalServiceType {
|
||||||
case latest.InternalServiceTypeAuto, latest.InternalServiceTypeClusterIP, latest.InternalServiceTypeHeadless:
|
case latest.InternalServiceTypeAuto, latest.InternalServiceTypeClusterIP, latest.InternalServiceTypeHeadless:
|
||||||
default:
|
default:
|
||||||
return latest.InternalServiceTypeAuto,
|
return errors.Errorf(`invalid value %q for field "x-kubernetes.internal_service_type", valid values are %q or %q`, internalServiceType,
|
||||||
errors.Errorf("invalid value %q for field %q, valid values are %q or %q", raw,
|
|
||||||
internalServiceTypeExtraField,
|
|
||||||
latest.InternalServiceTypeClusterIP,
|
latest.InternalServiceTypeClusterIP,
|
||||||
latest.InternalServiceTypeHeadless)
|
latest.InternalServiceTypeHeadless)
|
||||||
}
|
}
|
||||||
return internalServiceType, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toInternalPorts(expose []string) ([]latest.InternalPort, error) {
|
func toInternalPorts(expose []string) ([]latest.InternalPort, error) {
|
||||||
|
@ -385,15 +368,15 @@ func toInternalPorts(expose []string) ([]latest.InternalPort, error) {
|
||||||
return internalPorts, nil
|
return internalPorts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveServiceExtra(s composeTypes.ServiceConfig, field string) (string, error) {
|
func resolveServiceExtra(s composeTypes.ServiceConfig) (kubernetesExtra, error) {
|
||||||
if iface, ok := s.Extras[field]; ok {
|
if iface, ok := s.Extras[kubernatesExtraField]; ok {
|
||||||
value, ok := iface.(string)
|
var result kubernetesExtra
|
||||||
if !ok {
|
if err := mapstructure.Decode(iface, &result); err != nil {
|
||||||
return "", errors.Errorf("field %q: value %v type is %T, should be a string", field, iface, iface)
|
return kubernetesExtra{}, err
|
||||||
}
|
}
|
||||||
return value, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
return "", nil
|
return kubernetesExtra{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromComposePorts(ports []composeTypes.ServicePortConfig) []latest.ServicePortConfig {
|
func fromComposePorts(ports []composeTypes.ServicePortConfig) []latest.ServicePortConfig {
|
||||||
|
@ -576,3 +559,9 @@ type composeCapabilities struct {
|
||||||
hasPullPolicies bool
|
hasPullPolicies bool
|
||||||
hasIntraStackLoadBalancing bool
|
hasIntraStackLoadBalancing bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type kubernetesExtra struct {
|
||||||
|
PullSecret string `mapstructure:"pull_secret"`
|
||||||
|
PullPolicy string `mapstructure:"pull_policy"`
|
||||||
|
InternalServiceType latest.InternalServiceType `mapstructure:"internal_service_type"`
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
is "gotest.tools/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -189,8 +189,8 @@ func TestHandlePullSecret(t *testing.T) {
|
||||||
version string
|
version string
|
||||||
err 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: "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-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"},
|
{version: "v1alpha3"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,8 +216,8 @@ func TestHandlePullPolicy(t *testing.T) {
|
||||||
version string
|
version string
|
||||||
err 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: "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-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"},
|
{version: "v1alpha3"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,13 +249,13 @@ func TestHandleInternalServiceType(t *testing.T) {
|
||||||
name: "v1beta1",
|
name: "v1beta1",
|
||||||
value: "ClusterIP",
|
value: "ClusterIP",
|
||||||
caps: v1beta1Capabilities,
|
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",
|
name: "v1beta2",
|
||||||
value: "ClusterIP",
|
value: "ClusterIP",
|
||||||
caps: v1beta2Capabilities,
|
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",
|
name: "v1alpha3",
|
||||||
|
@ -267,7 +267,7 @@ func TestHandleInternalServiceType(t *testing.T) {
|
||||||
name: "v1alpha3-invalid",
|
name: "v1alpha3-invalid",
|
||||||
value: "invalid",
|
value: "invalid",
|
||||||
caps: v1alpha3Capabilities,
|
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 {
|
for _, c := range cases {
|
||||||
|
@ -276,7 +276,9 @@ func TestHandleInternalServiceType(t *testing.T) {
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Image: "test",
|
Image: "test",
|
||||||
Extras: map[string]interface{}{
|
Extras: map[string]interface{}{
|
||||||
internalServiceTypeExtraField: c.value,
|
"x-kubernetes": map[string]interface{}{
|
||||||
|
"internal_service_type": c.value,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, c.caps)
|
}, c.caps)
|
||||||
if c.err == "" {
|
if c.err == "" {
|
||||||
|
|
|
@ -2,4 +2,5 @@ version: "3.7"
|
||||||
services:
|
services:
|
||||||
test:
|
test:
|
||||||
image: "some-image"
|
image: "some-image"
|
||||||
x-pull-policy: "Never"
|
x-kubernetes:
|
||||||
|
pull_policy: "Never"
|
|
@ -2,4 +2,5 @@ version: "3.7"
|
||||||
services:
|
services:
|
||||||
test:
|
test:
|
||||||
image: "some-private-image"
|
image: "some-private-image"
|
||||||
x-pull-secret: "some-secret"
|
x-kubernetes:
|
||||||
|
pull_secret: "some-secret"
|
Loading…
Reference in New Issue