From 4d864a9aabfc1c0ac9282c9d5a775c478a43594e Mon Sep 17 00:00:00 2001 From: Hang Yan Date: Sun, 5 Jan 2020 11:35:32 +0800 Subject: [PATCH] Support deploy labels (#1231) --- docs/conversion.md | 2 +- pkg/kobject/kobject.go | 18 +-- pkg/loader/compose/v3.go | 121 ++++++++++-------- pkg/transformer/kubernetes/kubernetes.go | 4 +- pkg/transformer/utils.go | 12 ++ .../v3/docker-compose-deploy-mode.yaml | 2 + .../v3/output-deploy-mode-k8s-template.json | 1 + .../v3/output-deploy-mode-os-template.json | 1 + 8 files changed, 95 insertions(+), 66 deletions(-) diff --git a/docs/conversion.md b/docs/conversion.md index 5d9be45b..e52302f8 100644 --- a/docs/conversion.md +++ b/docs/conversion.md @@ -35,7 +35,7 @@ __Glossary:__ | deploy: update_config | - | - | n | | | | deploy: resources | - | - | ✓ | Containers.Resources.Limits.Memory / Containers.Resources.Limits.CPU | Support for memory as well as cpu | | deploy: restart_policy | - | - | ✓ | Pod generation | This generated a Pod, see the [user guide on restart](http://kompose.io/user-guide/#restart) | -| deploy: labels | - | - | n | | | +| deploy: labels | - | - | ✓ | Workload.Metadata.Labels | Only applied to workload resource | | | devices | x | x | x | | Not supported within Kubernetes, See issue https://github.com/kubernetes/kubernetes/issues/5607 | | depends_on | x | x | x | | | | dns | x | x | x | | Not used within Kubernetes. Kubernetes uses a managed DNS server | diff --git a/pkg/kobject/kobject.go b/pkg/kobject/kobject.go index 17faeb8b..eff29876 100644 --- a/pkg/kobject/kobject.go +++ b/pkg/kobject/kobject.go @@ -113,14 +113,16 @@ type ServiceConfig struct { MemLimit yaml.MemStringorInt `compose:"mem_limit"` MemReservation yaml.MemStringorInt `compose:""` DeployMode string `compose:""` - TmpFs []string `compose:"tmpfs"` - Dockerfile string `compose:"dockerfile"` - Replicas int `compose:"replicas"` - GroupAdd []int64 `compose:"group_add"` - Volumes []Volumes `compose:""` - Secrets []dockerCliTypes.ServiceSecretConfig - HealthChecks HealthCheck `compose:""` - Placement map[string]string `compose:""` + // DeployLabels mapping to kubernetes labels + DeployLabels map[string]string `compose:""` + TmpFs []string `compose:"tmpfs"` + Dockerfile string `compose:"dockerfile"` + Replicas int `compose:"replicas"` + GroupAdd []int64 `compose:"group_add"` + Volumes []Volumes `compose:""` + Secrets []dockerCliTypes.ServiceSecretConfig + HealthChecks HealthCheck `compose:""` + Placement map[string]string `compose:""` //This is for long LONG SYNTAX link(https://docs.docker.com/compose/compose-file/#long-syntax) Configs []dockerCliTypes.ServiceConfigObjConfig `compose:""` //This is for SHORT SYNTAX link(https://docs.docker.com/compose/compose-file/#configs) diff --git a/pkg/loader/compose/v3.go b/pkg/loader/compose/v3.go index 3d9ed29b..fd7d0e53 100755 --- a/pkg/loader/compose/v3.go +++ b/pkg/loader/compose/v3.go @@ -311,30 +311,17 @@ func dockerComposeToKomposeMapping(composeObject *types.Config) (kobject.Kompose serviceConfig.DomainName = composeServiceConfig.DomainName serviceConfig.Secrets = composeServiceConfig.Secrets - //Adding network key related info - if len(composeServiceConfig.Networks) == 0 { - if defaultNetwork, ok := composeObject.Networks["default"]; ok { - serviceConfig.Network = append(serviceConfig.Network, defaultNetwork.Name) - } - } else { - var alias = "" - for key := range composeServiceConfig.Networks { - alias = key - netName := composeObject.Networks[alias].Name - // if Network Name Field is empty in the docker-compose definition - // we will use the alias name defined in service config file - if netName == "" { - netName = alias - } - serviceConfig.Network = append(serviceConfig.Network, netName) - } - } - // - // Deploy keys - // + parseV3Network(&composeServiceConfig, &serviceConfig, composeObject) + if err := parseV3Resources(&composeServiceConfig, &serviceConfig); err != nil { + return kobject.KomposeObject{}, err + } + + // Deploy keys // mode: serviceConfig.DeployMode = composeServiceConfig.Deploy.Mode + // labels + serviceConfig.DeployLabels = composeServiceConfig.Deploy.Labels // HealthCheck if composeServiceConfig.HealthCheck != nil && !composeServiceConfig.HealthCheck.Disable { @@ -345,40 +332,6 @@ func dockerComposeToKomposeMapping(composeObject *types.Config) (kobject.Kompose } } - if (composeServiceConfig.Deploy.Resources != types.Resources{}) { - - // memory: - // TODO: Refactor yaml.MemStringorInt in kobject.go to int64 - // cpu: - // convert to k8s format, for example: 0.5 = 500m - // See: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ - // "The expression 0.1 is equivalent to the expression 100m, which can be read as “one hundred millicpu”." - - // Since Deploy.Resources.Limits does not initialize, we must check type Resources before continuing - if composeServiceConfig.Deploy.Resources.Limits != nil { - serviceConfig.MemLimit = libcomposeyaml.MemStringorInt(composeServiceConfig.Deploy.Resources.Limits.MemoryBytes) - - if composeServiceConfig.Deploy.Resources.Limits.NanoCPUs != "" { - cpuLimit, err := strconv.ParseFloat(composeServiceConfig.Deploy.Resources.Limits.NanoCPUs, 64) - if err != nil { - return kobject.KomposeObject{}, errors.Wrap(err, "Unable to convert cpu limits resources value") - } - serviceConfig.CPULimit = int64(cpuLimit * 1000) - } - } - if composeServiceConfig.Deploy.Resources.Reservations != nil { - serviceConfig.MemReservation = libcomposeyaml.MemStringorInt(composeServiceConfig.Deploy.Resources.Reservations.MemoryBytes) - - if composeServiceConfig.Deploy.Resources.Reservations.NanoCPUs != "" { - cpuReservation, err := strconv.ParseFloat(composeServiceConfig.Deploy.Resources.Reservations.NanoCPUs, 64) - if err != nil { - return kobject.KomposeObject{}, errors.Wrap(err, "Unable to convert cpu limits reservation value") - } - serviceConfig.CPUReservation = int64(cpuReservation * 1000) - } - } - } - // restart-policy: deploy.restart_policy.condition will rewrite restart option // see: https://docs.docker.com/compose/compose-file/#restart_policy serviceConfig.Restart = composeServiceConfig.Restart @@ -447,6 +400,64 @@ func dockerComposeToKomposeMapping(composeObject *types.Config) (kobject.Kompose return komposeObject, nil } +func parseV3Network(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig, composeObject *types.Config) { + if len(composeServiceConfig.Networks) == 0 { + if defaultNetwork, ok := composeObject.Networks["default"]; ok { + serviceConfig.Network = append(serviceConfig.Network, defaultNetwork.Name) + } + } else { + var alias = "" + for key := range composeServiceConfig.Networks { + alias = key + netName := composeObject.Networks[alias].Name + // if Network Name Field is empty in the docker-compose definition + // we will use the alias name defined in service config file + if netName == "" { + netName = alias + } + serviceConfig.Network = append(serviceConfig.Network, netName) + } + } +} + +func parseV3Resources(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig) error { + if (composeServiceConfig.Deploy.Resources != types.Resources{}) { + + // memory: + // TODO: Refactor yaml.MemStringorInt in kobject.go to int64 + // cpu: + // convert to k8s format, for example: 0.5 = 500m + // See: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + // "The expression 0.1 is equivalent to the expression 100m, which can be read as “one hundred millicpu”." + + // Since Deploy.Resources.Limits does not initialize, we must check type Resources before continuing + if composeServiceConfig.Deploy.Resources.Limits != nil { + serviceConfig.MemLimit = libcomposeyaml.MemStringorInt(composeServiceConfig.Deploy.Resources.Limits.MemoryBytes) + + if composeServiceConfig.Deploy.Resources.Limits.NanoCPUs != "" { + cpuLimit, err := strconv.ParseFloat(composeServiceConfig.Deploy.Resources.Limits.NanoCPUs, 64) + if err != nil { + return errors.Wrap(err, "Unable to convert cpu limits resources value") + } + serviceConfig.CPULimit = int64(cpuLimit * 1000) + } + } + if composeServiceConfig.Deploy.Resources.Reservations != nil { + serviceConfig.MemReservation = libcomposeyaml.MemStringorInt(composeServiceConfig.Deploy.Resources.Reservations.MemoryBytes) + + if composeServiceConfig.Deploy.Resources.Reservations.NanoCPUs != "" { + cpuReservation, err := strconv.ParseFloat(composeServiceConfig.Deploy.Resources.Reservations.NanoCPUs, 64) + if err != nil { + return errors.Wrap(err, "Unable to convert cpu limits reservation value") + } + serviceConfig.CPUReservation = int64(cpuReservation * 1000) + } + } + } + return nil + +} + func parseV3Environment(composeServiceConfig *types.ServiceConfig, serviceConfig *kobject.ServiceConfig) { // Gather the environment values // DockerCompose uses map[string]*string while we use []string diff --git a/pkg/transformer/kubernetes/kubernetes.go b/pkg/transformer/kubernetes/kubernetes.go index 8c7401b2..c3a6e6f5 100755 --- a/pkg/transformer/kubernetes/kubernetes.go +++ b/pkg/transformer/kubernetes/kubernetes.go @@ -393,7 +393,7 @@ func (k *Kubernetes) InitD(name string, service kobject.ServiceConfig, replicas }, ObjectMeta: api.ObjectMeta{ Name: name, - Labels: transformer.ConfigLabels(name), + Labels: transformer.ConfigAllLabels(name, &service), }, Spec: extensions.DeploymentSpec{ Replicas: int32(replicas), @@ -423,7 +423,7 @@ func (k *Kubernetes) InitDS(name string, service kobject.ServiceConfig) *extensi }, ObjectMeta: api.ObjectMeta{ Name: name, - Labels: transformer.ConfigLabels(name), + Labels: transformer.ConfigAllLabels(name, &service), }, Spec: extensions.DaemonSetSpec{ Template: api.PodTemplateSpec{ diff --git a/pkg/transformer/utils.go b/pkg/transformer/utils.go index 31b0da7d..a4242dc5 100644 --- a/pkg/transformer/utils.go +++ b/pkg/transformer/utils.go @@ -125,6 +125,18 @@ func ConfigLabelsWithNetwork(name string, net []string) map[string]string { //return map[string]string{Selector: name, "Network": net} } +// ConfigAllLabels creates labels with service nam and deploy labels +func ConfigAllLabels(name string, service *kobject.ServiceConfig) map[string]string { + base := ConfigLabels(name) + if service.DeployLabels != nil { + for k, v := range service.DeployLabels { + base[k] = v + } + } + return base + +} + // ConfigAnnotations configures annotations func ConfigAnnotations(service kobject.ServiceConfig) map[string]string { diff --git a/script/test/fixtures/v3/docker-compose-deploy-mode.yaml b/script/test/fixtures/v3/docker-compose-deploy-mode.yaml index 75d836fd..1be9f38c 100644 --- a/script/test/fixtures/v3/docker-compose-deploy-mode.yaml +++ b/script/test/fixtures/v3/docker-compose-deploy-mode.yaml @@ -7,4 +7,6 @@ services: deploy: mode: global replicas: 6 + labels: + com.example.description: "This label will appear on the web service" image: redis diff --git a/script/test/fixtures/v3/output-deploy-mode-k8s-template.json b/script/test/fixtures/v3/output-deploy-mode-k8s-template.json index e4b5817e..c4b8da49 100644 --- a/script/test/fixtures/v3/output-deploy-mode-k8s-template.json +++ b/script/test/fixtures/v3/output-deploy-mode-k8s-template.json @@ -46,6 +46,7 @@ }, "creationTimestamp": null, "labels": { + "com.example.description": "This label will appear on the web service", "io.kompose.service": "foo" }, "name": "foo" diff --git a/script/test/fixtures/v3/output-deploy-mode-os-template.json b/script/test/fixtures/v3/output-deploy-mode-os-template.json index f8095ee2..de028572 100644 --- a/script/test/fixtures/v3/output-deploy-mode-os-template.json +++ b/script/test/fixtures/v3/output-deploy-mode-os-template.json @@ -46,6 +46,7 @@ }, "creationTimestamp": null, "labels": { + "com.example.description": "This label will appear on the web service", "io.kompose.service": "foo" }, "name": "foo"