Add kompose.image-pull-secret and kompose.image-pull-policy (#1091)

* Add kompose.image-pull-secret

* Add kompose.image-pull-secret tests

* Add kompose.image-pull-policy

* Add kompose.image-pull-policy tests

* ignore .coverprofile

* Fix typo
This commit is contained in:
Kamil Kieliszczyk 2019-02-07 15:50:53 +01:00 committed by Charlie Drage
parent 40c1b8cf87
commit 66ac4aff4f
18 changed files with 387 additions and 7 deletions

3
.gitignore vendored
View File

@ -41,6 +41,9 @@ _testmain.go
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Coveralls files
.coverprofile
#
# VIM SPECIFIC
#

View File

@ -302,6 +302,8 @@ The currently supported options are:
| kompose.service.expose.tls-secret | secret name |
| kompose.volume.size | kubernetes supported volume size |
| kompose.controller.type | deployment / daemonset / replicationcontroller |
| kompose.image-pull-policy | kubernetes pods imagePullPolicy |
| kompose.image-pull-secret | kubernetes secret name for imagePullSecrets |
**Note**: `kompose.service.type` label should be defined with `ports` only (except for headless service), otherwise `kompose` will fail.
@ -350,6 +352,19 @@ services:
- "6379"
```
- `kompose.image-pull-secret` defines a kubernetes secret name for imagePullSecrets podspec field.
This secret will be used for pulling private images.
For example:
```yaml
version: '2'
services:
tm-service:
image: premium/private-image
labels:
kompose.image-pull-secret: "example-kubernetes-secret"
```
- `kompose.volume.size` defines the requests storage's size in the PersistentVolumeClaim
For example:
@ -399,6 +414,19 @@ db:
Service `web` will be converted to `Deployment` as default, service `db` will be converted to `DaemonSet` because of `kompose.controller.type` label.
- `kompose.image-pull-policy` defines Kubernetes PodSpec imagePullPolicy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise.
For example:
```yaml
version: '2'
services:
example-service:
image: example-image
labels:
kompose.image-pull-policy: "Never"
```
## Restart
If you want to create normal pods without controller you can use `restart` construct of docker-compose to define that. Follow table below to see what happens on the `restart` value.

View File

@ -85,6 +85,7 @@ type ServiceConfig struct {
CapAdd []string `compose:"cap_add"`
CapDrop []string `compose:"cap_drop"`
Expose []string `compose:"expose"`
ImagePullPolicy string `compose:"kompose.image-pull-policy"`
Pid string `compose:"pid"`
Privileged bool `compose:"privileged"`
Restart string `compose:"restart"`
@ -97,6 +98,7 @@ type ServiceConfig struct {
ExposeService string `compose:"kompose.service.expose"`
BuildLabels map[string]string `compose:"build-labels"`
ExposeServiceTLS string `compose:"kompose.service.expose.tls-secret"`
ImagePullSecret string `compose:"kompose.image-pull-secret"`
Stdin bool `compose:"stdin_open"`
Tty bool `compose:"tty"`
MemLimit yaml.MemStringorInt `compose:"mem_limit"`

View File

@ -37,6 +37,10 @@ const (
LabelServiceExposeTLSSecret = "kompose.service.expose.tls-secret"
// LabelControllerType defines the type of controller to be created
LabelControllerType = "kompose.controller.type"
// LabelImagePullSecret defines a secret name for kubernetes ImagePullSecrets
LabelImagePullSecret = "kompose.image-pull-secret"
// LabelImagePullPolicy defines Kubernetes PodSpec imagePullPolicy.
LabelImagePullPolicy = "kompose.image-pull-policy"
// ServiceTypeHeadless ...
ServiceTypeHeadless = "Headless"

View File

@ -246,6 +246,10 @@ func libComposeToKomposeMapping(composeObject *project.Project) (kobject.Kompose
serviceConfig.ExposeService = strings.Trim(strings.ToLower(value), " ,")
case LabelServiceExposeTLSSecret:
serviceConfig.ExposeServiceTLS = value
case LabelImagePullSecret:
serviceConfig.ImagePullSecret = value
case LabelImagePullPolicy:
serviceConfig.ImagePullPolicy = value
default:
serviceConfig.Labels[key] = value
}

View File

@ -401,6 +401,10 @@ func dockerComposeToKomposeMapping(composeObject *types.Config) (kobject.Kompose
serviceConfig.ExposeService = strings.Trim(strings.ToLower(value), " ,")
case LabelServiceExposeTLSSecret:
serviceConfig.ExposeServiceTLS = value
case LabelImagePullSecret:
serviceConfig.ImagePullSecret = value
case LabelImagePullPolicy:
serviceConfig.ImagePullPolicy = value
}
}

View File

@ -503,6 +503,19 @@ func (k *Kubernetes) UpdateKubernetesObjects(name string, service kobject.Servic
template.Spec.Containers[0].Ports = ports
template.ObjectMeta.Labels = transformer.ConfigLabels(name)
// Configure the image pull policy
switch service.ImagePullPolicy {
case "":
case "Always":
template.Spec.Containers[0].ImagePullPolicy = api.PullAlways
case "Never":
template.Spec.Containers[0].ImagePullPolicy = api.PullNever
case "IfNotPresent":
template.Spec.Containers[0].ImagePullPolicy = api.PullIfNotPresent
default:
return errors.New("Unknown image-pull-policy " + service.ImagePullPolicy + " for service " + name)
}
// Configure the container restart policy.
switch service.Restart {
case "", "always", "any":

View File

@ -116,7 +116,7 @@ func (k *Kubernetes) CheckUnsupportedKey(komposeObject *kobject.KomposeObject, u
}
// InitPodSpec creates the pod specification
func (k *Kubernetes) InitPodSpec(name string, image string) api.PodSpec {
func (k *Kubernetes) InitPodSpec(name string, image string, pullSecret string) api.PodSpec {
pod := api.PodSpec{
Containers: []api.Container{
{
@ -125,6 +125,13 @@ func (k *Kubernetes) InitPodSpec(name string, image string) api.PodSpec {
},
},
}
if pullSecret != "" {
pod.ImagePullSecrets = []api.LocalObjectReference{
{
Name: pullSecret,
},
}
}
return pod
}
@ -191,7 +198,7 @@ func (k *Kubernetes) InitRC(name string, service kobject.ServiceConfig, replicas
ObjectMeta: api.ObjectMeta{
Labels: transformer.ConfigLabels(name),
},
Spec: k.InitPodSpec(name, service.Image),
Spec: k.InitPodSpec(name, service.Image, service.ImagePullSecret),
},
},
}
@ -281,7 +288,7 @@ func (k *Kubernetes) InitD(name string, service kobject.ServiceConfig, replicas
if len(service.Configs) > 0 {
podSpec = k.InitPodSpecWithConfigMap(name, service.Image, service)
} else {
podSpec = k.InitPodSpec(name, service.Image)
podSpec = k.InitPodSpec(name, service.Image, service.ImagePullSecret)
}
dc := &extensions.Deployment{
@ -316,7 +323,7 @@ func (k *Kubernetes) InitDS(name string, service kobject.ServiceConfig) *extensi
},
Spec: extensions.DaemonSetSpec{
Template: api.PodTemplateSpec{
Spec: k.InitPodSpec(name, service.Image),
Spec: k.InitPodSpec(name, service.Image, service.ImagePullSecret),
},
},
}
@ -807,7 +814,7 @@ func (k *Kubernetes) InitPod(name string, service kobject.ServiceConfig) *api.Po
Name: name,
Labels: transformer.ConfigLabels(name),
},
Spec: k.InitPodSpec(name, service.Image),
Spec: k.InitPodSpec(name, service.Image, service.ImagePullSecret),
}
return &pod
}

View File

@ -489,7 +489,7 @@ func TestRestartOnFailure(t *testing.T) {
func TestInitPodSpec(t *testing.T) {
name := "foo"
k := Kubernetes{}
result := k.InitPodSpec(name, newServiceConfig().Image)
result := k.InitPodSpec(name, newServiceConfig().Image, "")
if result.Containers[0].Name != "foo" && result.Containers[0].Image != "image" {
t.Fatalf("Pod object not found")
}

View File

@ -187,7 +187,7 @@ func (o *OpenShift) initDeploymentConfig(name string, service kobject.ServiceCon
if len(service.Configs) > 0 {
podSpec = o.InitPodSpecWithConfigMap(name, " ", service)
} else {
podSpec = o.InitPodSpec(name, " ")
podSpec = o.InitPodSpec(name, " ", "")
}
dc := &deployapi.DeploymentConfig{

View File

@ -415,6 +415,25 @@ cmd="kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose-s
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/openshift-expose-hostname-multiple-ports.json > /tmp/output-os.json
convert::expect_success "kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-hostname-multiple-ports.yml convert --stdout -j" "/tmp/output-os.json"
# Test related to kompose.image-pull-secret label in docker compose file to ensure imagePullSecrets are populated properly.
# Kubernetes Test
cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/image-pull-secret/compose-files/docker-compose-image-pull-secret.yml convert --stdout -j"
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/image-pull-secret/provider-files/kubernetes-image-pull-secret.json > /tmp/output-k8s.json
convert::expect_success "$cmd" "/tmp/output-k8s.json"
# Test related to kompose.image-pull-secrets label in docker compose file.
# Kubernetes Tests
# when kompose.image-pull-secrets is invalid
convert::expect_failure "kompose -f $KOMPOSE_ROOT/script/test/fixtures/image-pull-policy/compose-files/v12-fail-image-pull-policy.yml convert --stdout"
# when kompose.image-pull-secrets in v1 and 2
cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/image-pull-policy/compose-files/v12-image-pull-policy.yml convert --stdout -j"
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/image-pull-policy/provider-files/kubernetes-v12-image-pull-policy.json > /tmp/output-k8s.json
convert::expect_success "$cmd" "/tmp/output-k8s.json"
# when kompose.image-pull-secrets in v3
cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/image-pull-policy/compose-files/v3-image-pull-policy.yml convert --stdout -j"
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/image-pull-policy/provider-files/kubernetes-v3-image-pull-policy.json > /tmp/output-k8s.json
convert::expect_success "$cmd" "/tmp/output-k8s.json"
# Test the change in the service name
# Kubernetes Test

View File

@ -0,0 +1,6 @@
version: "2"
services:
nginx0:
image: nginx
labels:
kompose.image-pull-policy: "Fail"

View File

@ -0,0 +1,7 @@
version: "2"
services:
nginx0:
image: nginx
labels:
kompose.image-pull-policy: "Always"

View File

@ -0,0 +1,14 @@
version: "3"
services:
nginx0:
image: nginx
labels:
kompose.image-pull-policy: "Always"
nginx1:
image: nginx
labels:
kompose.image-pull-policy: "IfNotPresent"
nginx2:
image: nginx
labels:
kompose.image-pull-policy: "Never"

View File

@ -0,0 +1,47 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "nginx0",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx0"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.image-pull-policy": "Always",
"kompose.version": "%VERSION%"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx0"
}
},
"spec": {
"containers": [
{
"name": "nginx0",
"image": "nginx",
"resources": {},
"imagePullPolicy": "Always"
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
}
]
}

View File

@ -0,0 +1,127 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "nginx0",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx0"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.image-pull-policy": "Always",
"kompose.version": "%VERSION%"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx0"
}
},
"spec": {
"containers": [
{
"name": "nginx0",
"image": "nginx",
"resources": {},
"imagePullPolicy": "Always"
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "nginx1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx1"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.image-pull-policy": "IfNotPresent",
"kompose.version": "%VERSION%"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx1"
}
},
"spec": {
"containers": [
{
"name": "nginx1",
"image": "nginx",
"resources": {},
"imagePullPolicy": "IfNotPresent"
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "nginx2",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx2"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.image-pull-policy": "Never",
"kompose.version": "%VERSION%"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx2"
}
},
"spec": {
"containers": [
{
"name": "nginx2",
"image": "nginx",
"resources": {},
"imagePullPolicy": "Never"
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
}
]
}

View File

@ -0,0 +1,6 @@
tm-image-service:
image: premium/private-image
labels:
kompose.image-pull-secret: "sample-k8s-secret-name"
open-image-service:
image: nginx-alpine

View File

@ -0,0 +1,89 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "open-image-service",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "open-image-service"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "open-image-service"
}
},
"spec": {
"containers": [
{
"name": "open-image-service",
"image": "nginx-alpine",
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "tm-image-service",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "tm-image-service"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.image-pull-secret": "sample-k8s-secret-name",
"kompose.version": "%VERSION%"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "tm-image-service"
}
},
"spec": {
"containers": [
{
"name": "tm-image-service",
"image": "premium/private-image",
"resources": {}
}
],
"restartPolicy": "Always",
"imagePullSecrets": [
{
"name": "sample-k8s-secret-name"
}
]
}
},
"strategy": {}
},
"status": {}
}
]
}