2017-11-20 09:30:52 -05:00
package kubernetes
import (
2018-02-26 09:59:44 -05:00
"io"
"io/ioutil"
2018-01-31 09:37:14 -05:00
"regexp"
"strconv"
"strings"
"github.com/docker/cli/cli/compose/loader"
2018-06-27 10:41:00 -04:00
"github.com/docker/cli/cli/compose/schema"
2018-01-31 09:37:14 -05:00
composeTypes "github.com/docker/cli/cli/compose/types"
composetypes "github.com/docker/cli/cli/compose/types"
2019-01-16 06:56:37 -05:00
latest "github.com/docker/compose-on-kubernetes/api/compose/v1alpha3"
2018-12-20 02:45:35 -05:00
"github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
2019-04-08 04:37:18 -04:00
"github.com/docker/go-connections/nat"
2019-04-12 09:18:45 -04:00
"github.com/mitchellh/mapstructure"
2018-06-27 10:41:00 -04:00
"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"
2019-04-08 04:37:18 -04:00
v1 "k8s.io/api/core/v1"
2017-11-20 09:30:52 -05:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
2019-01-28 10:54:38 -05:00
const (
2019-04-12 09:18:45 -04:00
// kubernatesExtraField is an extra field on ServiceConfigs containing kubernetes-specific extensions to compose format
kubernatesExtraField = "x-kubernetes"
2019-01-28 10:54:38 -05:00
)
2018-06-27 10:41:00 -04:00
// NewStackConverter returns a converter from types.Config (compose) to the specified
// stack version or error out if the version is not supported or existent.
func NewStackConverter ( version string ) ( StackConverter , error ) {
switch version {
case "v1beta1" :
return stackV1Beta1Converter { } , nil
2019-01-28 10:54:38 -05:00
case "v1beta2" :
return stackV1Beta2Converter { } , nil
case "v1alpha3" :
return stackV1Alpha3Converter { } , nil
2018-06-27 10:41:00 -04:00
default :
return nil , errors . Errorf ( "stack version %s unsupported" , version )
}
}
// StackConverter converts a compose types.Config to a Stack
type StackConverter interface {
FromCompose ( stderr io . Writer , name string , cfg * composetypes . Config ) ( Stack , error )
}
type stackV1Beta1Converter struct { }
func ( s stackV1Beta1Converter ) FromCompose ( stderr io . Writer , name string , cfg * composetypes . Config ) ( Stack , error ) {
cfg . Version = v1beta1 . MaxComposeVersion
2019-01-28 10:54:38 -05:00
st , err := fromCompose ( stderr , name , cfg , v1beta1Capabilities )
2018-06-27 10:41:00 -04:00
if err != nil {
return Stack { } , err
}
res , err := yaml . Marshal ( cfg )
if err != nil {
return Stack { } , err
}
// reload the result to check that it produced a valid 3.5 compose file
resparsedConfig , err := loader . ParseYAML ( res )
if err != nil {
return Stack { } , err
}
if err = schema . Validate ( resparsedConfig , v1beta1 . MaxComposeVersion ) ; err != nil {
return Stack { } , errors . Wrapf ( err , "the compose yaml file is invalid with v%s" , v1beta1 . MaxComposeVersion )
}
st . ComposeFile = string ( res )
return st , nil
}
2019-01-28 10:54:38 -05:00
type stackV1Beta2Converter struct { }
2018-06-27 10:41:00 -04:00
2019-01-28 10:54:38 -05:00
func ( s stackV1Beta2Converter ) FromCompose ( stderr io . Writer , name string , cfg * composetypes . Config ) ( Stack , error ) {
return fromCompose ( stderr , name , cfg , v1beta2Capabilities )
2018-06-27 10:41:00 -04:00
}
2019-01-28 10:54:38 -05:00
type stackV1Alpha3Converter struct { }
func ( s stackV1Alpha3Converter ) FromCompose ( stderr io . Writer , name string , cfg * composetypes . Config ) ( Stack , error ) {
return fromCompose ( stderr , name , cfg , v1alpha3Capabilities )
}
func fromCompose ( stderr io . Writer , name string , cfg * composetypes . Config , capabilities composeCapabilities ) ( Stack , error ) {
spec , err := fromComposeConfig ( stderr , cfg , capabilities )
if err != nil {
return Stack { } , err
}
2018-06-27 10:41:00 -04:00
return Stack {
Name : name ,
2019-01-28 10:54:38 -05:00
Spec : spec ,
2018-06-27 10:41:00 -04:00
} , nil
}
2018-01-31 09:37:14 -05:00
func loadStackData ( composefile string ) ( * composetypes . Config , error ) {
parsed , err := loader . ParseYAML ( [ ] byte ( composefile ) )
if err != nil {
return nil , err
}
return loader . Load ( composetypes . ConfigDetails {
ConfigFiles : [ ] composetypes . ConfigFile {
{
Config : parsed ,
} ,
2017-11-20 09:30:52 -05:00
} ,
2018-01-31 09:37:14 -05:00
} )
}
// Conversions from internal stack to different stack compose component versions.
2018-06-27 10:41:00 -04:00
func stackFromV1beta1 ( in * v1beta1 . Stack ) ( Stack , error ) {
2018-01-31 09:37:14 -05:00
cfg , err := loadStackData ( in . Spec . ComposeFile )
if err != nil {
2018-06-27 10:41:00 -04:00
return Stack { } , err
2018-01-31 09:37:14 -05:00
}
2019-01-28 10:54:38 -05:00
spec , err := fromComposeConfig ( ioutil . Discard , cfg , v1beta1Capabilities )
if err != nil {
return Stack { } , err
}
2018-06-27 10:41:00 -04:00
return Stack {
Name : in . ObjectMeta . Name ,
Namespace : in . ObjectMeta . Namespace ,
ComposeFile : in . Spec . ComposeFile ,
2019-01-28 10:54:38 -05:00
Spec : spec ,
2018-01-31 09:37:14 -05:00
} , nil
}
2018-06-27 10:41:00 -04:00
func stackToV1beta1 ( s Stack ) * v1beta1 . Stack {
2018-01-31 09:37:14 -05:00
return & v1beta1 . Stack {
2017-11-20 09:30:52 -05:00
ObjectMeta : metav1 . ObjectMeta {
2018-06-27 10:41:00 -04:00
Name : s . Name ,
2017-11-20 09:30:52 -05:00
} ,
2018-01-31 09:37:14 -05:00
Spec : v1beta1 . StackSpec {
2018-06-27 10:41:00 -04:00
ComposeFile : s . ComposeFile ,
2017-11-20 09:30:52 -05:00
} ,
}
}
2019-01-16 06:56:37 -05:00
func stackFromV1beta2 ( in * v1beta2 . Stack ) ( Stack , error ) {
var spec * latest . StackSpec
if in . Spec != nil {
spec = & latest . StackSpec { }
if err := latest . Convert_v1beta2_StackSpec_To_v1alpha3_StackSpec ( in . Spec , spec , nil ) ; err != nil {
return Stack { } , err
}
}
return Stack {
Name : in . ObjectMeta . Name ,
Namespace : in . ObjectMeta . Namespace ,
Spec : spec ,
} , nil
}
func stackToV1beta2 ( s Stack ) ( * v1beta2 . Stack , error ) {
var spec * v1beta2 . StackSpec
if s . Spec != nil {
spec = & v1beta2 . StackSpec { }
if err := latest . Convert_v1alpha3_StackSpec_To_v1beta2_StackSpec ( s . Spec , spec , nil ) ; err != nil {
return nil , err
}
}
return & v1beta2 . Stack {
ObjectMeta : metav1 . ObjectMeta {
Name : s . Name ,
} ,
Spec : spec ,
} , nil
}
func stackFromV1alpha3 ( in * latest . Stack ) Stack {
2018-06-27 10:41:00 -04:00
return Stack {
Name : in . ObjectMeta . Name ,
Namespace : in . ObjectMeta . Namespace ,
Spec : in . Spec ,
2018-01-31 09:37:14 -05:00
}
}
2019-01-16 06:56:37 -05:00
func stackToV1alpha3 ( s Stack ) * latest . Stack {
return & latest . Stack {
2017-11-20 09:30:52 -05:00
ObjectMeta : metav1 . ObjectMeta {
2018-06-27 10:41:00 -04:00
Name : s . Name ,
2017-11-20 09:30:52 -05:00
} ,
2018-06-27 10:41:00 -04:00
Spec : s . Spec ,
2018-01-31 09:37:14 -05:00
}
}
2019-01-28 10:54:38 -05:00
func fromComposeConfig ( stderr io . Writer , c * composeTypes . Config , capabilities composeCapabilities ) ( * latest . StackSpec , error ) {
2018-01-31 09:37:14 -05:00
if c == nil {
2019-01-28 10:54:38 -05:00
return nil , nil
2018-01-31 09:37:14 -05:00
}
2018-02-26 09:59:44 -05:00
warnUnsupportedFeatures ( stderr , c )
2019-01-16 06:56:37 -05:00
serviceConfigs := make ( [ ] latest . ServiceConfig , len ( c . Services ) )
2018-01-31 09:37:14 -05:00
for i , s := range c . Services {
2019-01-28 10:54:38 -05:00
svc , err := fromComposeServiceConfig ( s , capabilities )
if err != nil {
return nil , err
}
serviceConfigs [ i ] = svc
2018-01-31 09:37:14 -05:00
}
2019-01-16 06:56:37 -05:00
return & latest . StackSpec {
2018-01-31 09:37:14 -05:00
Services : serviceConfigs ,
Secrets : fromComposeSecrets ( c . Secrets ) ,
Configs : fromComposeConfigs ( c . Configs ) ,
2019-01-28 10:54:38 -05:00
} , nil
2018-01-31 09:37:14 -05:00
}
2019-01-16 06:56:37 -05:00
func fromComposeSecrets ( s map [ string ] composeTypes . SecretConfig ) map [ string ] latest . SecretConfig {
2018-01-31 09:37:14 -05:00
if s == nil {
return nil
}
2019-01-16 06:56:37 -05:00
m := map [ string ] latest . SecretConfig { }
2018-01-31 09:37:14 -05:00
for key , value := range s {
2019-01-16 06:56:37 -05:00
m [ key ] = latest . SecretConfig {
2018-01-31 09:37:14 -05:00
Name : value . Name ,
File : value . File ,
2019-01-16 06:56:37 -05:00
External : latest . External {
2018-01-31 09:37:14 -05:00
Name : value . External . Name ,
External : value . External . External ,
} ,
Labels : value . Labels ,
}
}
return m
}
2019-01-16 06:56:37 -05:00
func fromComposeConfigs ( s map [ string ] composeTypes . ConfigObjConfig ) map [ string ] latest . ConfigObjConfig {
2018-01-31 09:37:14 -05:00
if s == nil {
return nil
}
2019-01-16 06:56:37 -05:00
m := map [ string ] latest . ConfigObjConfig { }
2018-01-31 09:37:14 -05:00
for key , value := range s {
2019-01-16 06:56:37 -05:00
m [ key ] = latest . ConfigObjConfig {
2018-01-31 09:37:14 -05:00
Name : value . Name ,
File : value . File ,
2019-01-16 06:56:37 -05:00
External : latest . External {
2018-01-31 09:37:14 -05:00
Name : value . External . Name ,
External : value . External . External ,
} ,
Labels : value . Labels ,
}
}
return m
}
2019-01-28 10:54:38 -05:00
func fromComposeServiceConfig ( s composeTypes . ServiceConfig , capabilities composeCapabilities ) ( latest . ServiceConfig , error ) {
var (
2019-04-12 09:18:45 -04:00
userID * int64
err error
2019-01-28 10:54:38 -05:00
)
2018-01-31 09:37:14 -05:00
if s . User != "" {
numerical , err := strconv . Atoi ( s . User )
if err == nil {
unixUserID := int64 ( numerical )
userID = & unixUserID
}
}
2019-04-12 09:18:45 -04:00
kubeExtra , err := resolveServiceExtra ( s )
2019-01-28 10:54:38 -05:00
if err != nil {
return latest . ServiceConfig { } , err
}
2019-04-12 09:18:45 -04:00
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 )
2019-01-28 10:54:38 -05:00
}
2019-04-12 09:18:45 -04:00
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 )
2019-01-28 10:54:38 -05:00
}
2019-04-08 04:37:18 -04:00
2019-04-12 09:18:45 -04:00
internalPorts , err := setupIntraStackNetworking ( s , kubeExtra , capabilities )
2019-04-08 04:37:18 -04:00
if err != nil {
return latest . ServiceConfig { } , err
}
2019-01-16 06:56:37 -05:00
return latest . ServiceConfig {
2018-01-31 09:37:14 -05:00
Name : s . Name ,
CapAdd : s . CapAdd ,
CapDrop : s . CapDrop ,
Command : s . Command ,
Configs : fromComposeServiceConfigs ( s . Configs ) ,
2019-01-16 06:56:37 -05:00
Deploy : latest . DeployConfig {
2018-01-31 09:37:14 -05:00
Mode : s . Deploy . Mode ,
Replicas : s . Deploy . Replicas ,
Labels : s . Deploy . Labels ,
UpdateConfig : fromComposeUpdateConfig ( s . Deploy . UpdateConfig ) ,
Resources : fromComposeResources ( s . Deploy . Resources ) ,
RestartPolicy : fromComposeRestartPolicy ( s . Deploy . RestartPolicy ) ,
Placement : fromComposePlacement ( s . Deploy . Placement ) ,
2017-11-20 09:30:52 -05:00
} ,
2019-04-08 04:37:18 -04:00
Entrypoint : s . Entrypoint ,
Environment : s . Environment ,
ExtraHosts : s . ExtraHosts ,
Hostname : s . Hostname ,
HealthCheck : fromComposeHealthcheck ( s . HealthCheck ) ,
Image : s . Image ,
Ipc : s . Ipc ,
Labels : s . Labels ,
Pid : s . Pid ,
Ports : fromComposePorts ( s . Ports ) ,
Privileged : s . Privileged ,
ReadOnly : s . ReadOnly ,
Secrets : fromComposeServiceSecrets ( s . Secrets ) ,
StdinOpen : s . StdinOpen ,
StopGracePeriod : composetypes . ConvertDurationPtr ( s . StopGracePeriod ) ,
Tmpfs : s . Tmpfs ,
Tty : s . Tty ,
User : userID ,
Volumes : fromComposeServiceVolumeConfig ( s . Volumes ) ,
WorkingDir : s . WorkingDir ,
2019-04-12 09:18:45 -04:00
PullSecret : kubeExtra . PullSecret ,
PullPolicy : kubeExtra . PullPolicy ,
InternalServiceType : kubeExtra . InternalServiceType ,
2019-04-08 04:37:18 -04:00
InternalPorts : internalPorts ,
2019-01-28 10:54:38 -05:00
} , nil
}
2019-04-12 09:18:45 -04:00
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 )
2019-04-08 04:37:18 -04:00
}
if ! capabilities . hasIntraStackLoadBalancing {
2019-04-12 09:18:45 -04:00
return nil , nil
2019-04-08 04:37:18 -04:00
}
2019-04-12 09:18:45 -04:00
if err := validateInternalServiceType ( kubeExtra . InternalServiceType ) ; err != nil {
return nil , err
2019-04-08 04:37:18 -04:00
}
internalPorts , err := toInternalPorts ( s . Expose )
if err != nil {
2019-04-12 09:18:45 -04:00
return nil , err
2019-04-08 04:37:18 -04:00
}
2019-04-12 09:18:45 -04:00
return internalPorts , nil
2019-04-08 04:37:18 -04:00
}
2019-04-12 09:18:45 -04:00
func validateInternalServiceType ( internalServiceType latest . InternalServiceType ) error {
2019-04-08 04:37:18 -04:00
switch internalServiceType {
case latest . InternalServiceTypeAuto , latest . InternalServiceTypeClusterIP , latest . InternalServiceTypeHeadless :
default :
2019-04-12 09:18:45 -04:00
return errors . Errorf ( ` invalid value %q for field "x-kubernetes.internal_service_type", valid values are %q or %q ` , internalServiceType ,
latest . InternalServiceTypeClusterIP ,
latest . InternalServiceTypeHeadless )
2019-04-08 04:37:18 -04:00
}
2019-04-12 09:18:45 -04:00
return nil
2019-04-08 04:37:18 -04:00
}
func toInternalPorts ( expose [ ] string ) ( [ ] latest . InternalPort , error ) {
var internalPorts [ ] latest . InternalPort
for _ , sourcePort := range expose {
proto , port := nat . SplitProtoPort ( sourcePort )
start , end , err := nat . ParsePortRange ( port )
if err != nil {
return nil , errors . Errorf ( "invalid format for expose: %q, error: %s" , sourcePort , err )
}
for i := start ; i <= end ; i ++ {
k8sProto := v1 . Protocol ( strings . ToUpper ( proto ) )
switch k8sProto {
case v1 . ProtocolSCTP , v1 . ProtocolTCP , v1 . ProtocolUDP :
default :
return nil , errors . Errorf ( "invalid protocol for expose: %q, supported values are %q, %q and %q" , sourcePort , v1 . ProtocolSCTP , v1 . ProtocolTCP , v1 . ProtocolUDP )
}
internalPorts = append ( internalPorts , latest . InternalPort {
Port : int32 ( i ) ,
Protocol : k8sProto ,
} )
}
}
return internalPorts , nil
}
2019-04-12 09:18:45 -04:00
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
2019-01-28 10:54:38 -05:00
}
2019-04-12 09:18:45 -04:00
return result , nil
2018-01-31 09:37:14 -05:00
}
2019-04-12 09:18:45 -04:00
return kubernetesExtra { } , nil
2018-01-31 09:37:14 -05:00
}
2019-01-16 06:56:37 -05:00
func fromComposePorts ( ports [ ] composeTypes . ServicePortConfig ) [ ] latest . ServicePortConfig {
2018-01-31 09:37:14 -05:00
if ports == nil {
return nil
}
2019-01-16 06:56:37 -05:00
p := make ( [ ] latest . ServicePortConfig , len ( ports ) )
2018-01-31 09:37:14 -05:00
for i , port := range ports {
2019-01-16 06:56:37 -05:00
p [ i ] = latest . ServicePortConfig {
2018-01-31 09:37:14 -05:00
Mode : port . Mode ,
Target : port . Target ,
Published : port . Published ,
Protocol : port . Protocol ,
}
}
return p
}
2019-01-16 06:56:37 -05:00
func fromComposeServiceSecrets ( secrets [ ] composeTypes . ServiceSecretConfig ) [ ] latest . ServiceSecretConfig {
2018-01-31 09:37:14 -05:00
if secrets == nil {
return nil
}
2019-01-16 06:56:37 -05:00
c := make ( [ ] latest . ServiceSecretConfig , len ( secrets ) )
2018-01-31 09:37:14 -05:00
for i , secret := range secrets {
2019-01-16 06:56:37 -05:00
c [ i ] = latest . ServiceSecretConfig {
2018-01-31 09:37:14 -05:00
Source : secret . Source ,
Target : secret . Target ,
UID : secret . UID ,
Mode : secret . Mode ,
}
}
return c
}
2019-01-16 06:56:37 -05:00
func fromComposeServiceConfigs ( configs [ ] composeTypes . ServiceConfigObjConfig ) [ ] latest . ServiceConfigObjConfig {
2018-01-31 09:37:14 -05:00
if configs == nil {
return nil
}
2019-01-16 06:56:37 -05:00
c := make ( [ ] latest . ServiceConfigObjConfig , len ( configs ) )
2018-01-31 09:37:14 -05:00
for i , config := range configs {
2019-01-16 06:56:37 -05:00
c [ i ] = latest . ServiceConfigObjConfig {
2018-01-31 09:37:14 -05:00
Source : config . Source ,
Target : config . Target ,
UID : config . UID ,
Mode : config . Mode ,
}
}
return c
}
2019-01-16 06:56:37 -05:00
func fromComposeHealthcheck ( h * composeTypes . HealthCheckConfig ) * latest . HealthCheckConfig {
2018-01-31 09:37:14 -05:00
if h == nil {
return nil
}
2019-01-16 06:56:37 -05:00
return & latest . HealthCheckConfig {
2018-01-31 09:37:14 -05:00
Test : h . Test ,
2018-08-29 17:29:39 -04:00
Timeout : composetypes . ConvertDurationPtr ( h . Timeout ) ,
Interval : composetypes . ConvertDurationPtr ( h . Interval ) ,
2018-01-31 09:37:14 -05:00
Retries : h . Retries ,
}
}
2019-01-16 06:56:37 -05:00
func fromComposePlacement ( p composeTypes . Placement ) latest . Placement {
return latest . Placement {
2018-01-31 09:37:14 -05:00
Constraints : fromComposeConstraints ( p . Constraints ) ,
}
}
var constraintEquals = regexp . MustCompile ( ` ([\w\.]*)\W*(==|!=)\W*([\w\.]*) ` )
const (
swarmOs = "node.platform.os"
swarmArch = "node.platform.arch"
swarmHostname = "node.hostname"
swarmLabelPrefix = "node.labels."
)
2019-01-16 06:56:37 -05:00
func fromComposeConstraints ( s [ ] string ) * latest . Constraints {
2018-01-31 09:37:14 -05:00
if len ( s ) == 0 {
return nil
}
2019-01-16 06:56:37 -05:00
constraints := & latest . Constraints { }
2018-01-31 09:37:14 -05:00
for _ , constraint := range s {
matches := constraintEquals . FindStringSubmatch ( constraint )
if len ( matches ) == 4 {
key := matches [ 1 ]
operator := matches [ 2 ]
value := matches [ 3 ]
2019-01-16 06:56:37 -05:00
constraint := & latest . Constraint {
2018-01-31 09:37:14 -05:00
Operator : operator ,
Value : value ,
}
switch {
case key == swarmOs :
constraints . OperatingSystem = constraint
case key == swarmArch :
constraints . Architecture = constraint
case key == swarmHostname :
constraints . Hostname = constraint
case strings . HasPrefix ( key , swarmLabelPrefix ) :
if constraints . MatchLabels == nil {
2019-01-16 06:56:37 -05:00
constraints . MatchLabels = map [ string ] latest . Constraint { }
2018-01-31 09:37:14 -05:00
}
constraints . MatchLabels [ strings . TrimPrefix ( key , swarmLabelPrefix ) ] = * constraint
}
}
}
return constraints
}
2019-01-16 06:56:37 -05:00
func fromComposeResources ( r composeTypes . Resources ) latest . Resources {
return latest . Resources {
2018-01-31 09:37:14 -05:00
Limits : fromComposeResourcesResource ( r . Limits ) ,
Reservations : fromComposeResourcesResource ( r . Reservations ) ,
}
}
2019-01-16 06:56:37 -05:00
func fromComposeResourcesResource ( r * composeTypes . Resource ) * latest . Resource {
2018-01-31 09:37:14 -05:00
if r == nil {
return nil
}
2019-01-16 06:56:37 -05:00
return & latest . Resource {
2018-01-31 09:37:14 -05:00
MemoryBytes : int64 ( r . MemoryBytes ) ,
NanoCPUs : r . NanoCPUs ,
}
}
2019-01-16 06:56:37 -05:00
func fromComposeUpdateConfig ( u * composeTypes . UpdateConfig ) * latest . UpdateConfig {
2018-01-31 09:37:14 -05:00
if u == nil {
return nil
}
2019-01-16 06:56:37 -05:00
return & latest . UpdateConfig {
2018-01-31 09:37:14 -05:00
Parallelism : u . Parallelism ,
}
}
2019-01-16 06:56:37 -05:00
func fromComposeRestartPolicy ( r * composeTypes . RestartPolicy ) * latest . RestartPolicy {
2018-01-31 09:37:14 -05:00
if r == nil {
return nil
}
2019-01-16 06:56:37 -05:00
return & latest . RestartPolicy {
2018-01-31 09:37:14 -05:00
Condition : r . Condition ,
}
}
2019-01-16 06:56:37 -05:00
func fromComposeServiceVolumeConfig ( vs [ ] composeTypes . ServiceVolumeConfig ) [ ] latest . ServiceVolumeConfig {
2018-01-31 09:37:14 -05:00
if vs == nil {
return nil
}
2019-01-16 06:56:37 -05:00
volumes := [ ] latest . ServiceVolumeConfig { }
2018-01-31 09:37:14 -05:00
for _ , v := range vs {
2019-01-16 06:56:37 -05:00
volumes = append ( volumes , latest . ServiceVolumeConfig {
2018-01-31 09:37:14 -05:00
Type : v . Type ,
Source : v . Source ,
Target : v . Target ,
ReadOnly : v . ReadOnly ,
} )
2017-11-20 09:30:52 -05:00
}
2018-01-31 09:37:14 -05:00
return volumes
2017-11-20 09:30:52 -05:00
}
2019-01-28 10:54:38 -05:00
var (
v1beta1Capabilities = composeCapabilities {
apiVersion : "v1beta1" ,
}
v1beta2Capabilities = composeCapabilities {
apiVersion : "v1beta2" ,
}
v1alpha3Capabilities = composeCapabilities {
2019-04-08 04:37:18 -04:00
apiVersion : "v1alpha3" ,
hasPullSecrets : true ,
hasPullPolicies : true ,
hasIntraStackLoadBalancing : true ,
2019-01-28 10:54:38 -05:00
}
)
type composeCapabilities struct {
2019-04-08 04:37:18 -04:00
apiVersion string
hasPullSecrets bool
hasPullPolicies bool
hasIntraStackLoadBalancing bool
2019-01-28 10:54:38 -05:00
}
2019-04-12 09:18:45 -04:00
type kubernetesExtra struct {
PullSecret string ` mapstructure:"pull_secret" `
PullPolicy string ` mapstructure:"pull_policy" `
InternalServiceType latest . InternalServiceType ` mapstructure:"internal_service_type" `
}