diff --git a/docs/user-guide.md b/docs/user-guide.md index c5a3d3cf..ce01d2d6 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -306,3 +306,27 @@ services: labels: kompose.service.type: nodeport ``` + +## Restart + +If you want to create normal pods without controllers you can use `restart` construct of docker-compose to define that. Follow table below to see what heppens on the `restart` value. + +| `docker-compose` `restart` | object created | Pod `restartPolicy` | +|----------------------------|-------------------|---------------------| +| `""` | controller object | `Always` | +| `always` | controller object | `Always` | +| `on-failure` | Pod | `OnFailure` | +| `no` | Pod | `Never` | + +**Note**: controller object could be `deployment` or `replicationcontroller`, etc. + +For e.g. `mariadb` service will become pod down here. + +```yaml +version: "2" + +services: + mariadb: + image: centos/mariadb + restart: "no" +``` \ No newline at end of file diff --git a/pkg/transformer/kubernetes/k8sutils.go b/pkg/transformer/kubernetes/k8sutils.go index 3b66016f..5e36b5eb 100644 --- a/pkg/transformer/kubernetes/k8sutils.go +++ b/pkg/transformer/kubernetes/k8sutils.go @@ -185,6 +185,8 @@ func PrintList(objects []runtime.Object, opt kobject.ConvertOptions) error { file = transformer.Print(t.Name, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f) case *api.PersistentVolumeClaim: file = transformer.Print(t.Name, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f) + case *api.Pod: + file = transformer.Print(t.Name, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f) } files = append(files, file) } diff --git a/pkg/transformer/kubernetes/kubernetes.go b/pkg/transformer/kubernetes/kubernetes.go index 25f06b60..6746cf7c 100644 --- a/pkg/transformer/kubernetes/kubernetes.go +++ b/pkg/transformer/kubernetes/kubernetes.go @@ -326,6 +326,27 @@ func (k *Kubernetes) CreateKubernetesObjects(name string, service kobject.Servic return objects } +func (k *Kubernetes) InitPod(name string, service kobject.ServiceConfig) *api.Pod { + pod := api.Pod{ + TypeMeta: unversioned.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + }, + ObjectMeta: api.ObjectMeta{ + Name: name, + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: name, + Image: service.Image, + }, + }, + }, + } + return &pod +} + // Transform maps komposeObject to k8s objects // returns object that are already sorted in the way that Services are first func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object { @@ -333,12 +354,19 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject. var allobjects []runtime.Object for name, service := range komposeObject.ServiceConfigs { - objects := k.CreateKubernetesObjects(name, service, opt) + var objects []runtime.Object - // If ports not provided in configuration we will not make service - if k.PortsExist(name, service) { - svc := k.CreateService(name, service, objects) - objects = append(objects, svc) + // Generate pod only and nothing more + if service.Restart == "no" || service.Restart == "on-failure" { + pod := k.InitPod(name, service) + objects = append(objects, pod) + } else { + objects = k.CreateKubernetesObjects(name, service, opt) + // If ports not provided in configuration we will not make service + if k.PortsExist(name, service) { + svc := k.CreateService(name, service, objects) + objects = append(objects, svc) + } } k.UpdateKubernetesObjects(name, service, &objects) @@ -370,6 +398,14 @@ func (k *Kubernetes) UpdateController(obj runtime.Object, updateTemplate func(*a case *deployapi.DeploymentConfig: updateTemplate(t.Spec.Template) updateMeta(&t.ObjectMeta) + case *api.Pod: + p := api.PodTemplateSpec{ + ObjectMeta: t.ObjectMeta, + Spec: t.Spec, + } + updateTemplate(&p) + t.Spec = p.Spec + t.ObjectMeta = p.ObjectMeta } } diff --git a/pkg/transformer/kubernetes/kubernetes_test.go b/pkg/transformer/kubernetes/kubernetes_test.go index 8e52a5d0..0c80e6e5 100644 --- a/pkg/transformer/kubernetes/kubernetes_test.go +++ b/pkg/transformer/kubernetes/kubernetes_test.go @@ -319,3 +319,37 @@ func TestKomposeConvert(t *testing.T) { } } } + +func TestConvertRestartOptions(t *testing.T) { + var opt kobject.ConvertOptions + var k Kubernetes + + testCases := map[string]struct { + svc kobject.KomposeObject + restartPolicy api.RestartPolicy + }{ + "'restart' is set to 'no'": {kobject.KomposeObject{ServiceConfigs: map[string]kobject.ServiceConfig{"app": kobject.ServiceConfig{Image: "foobar", Restart: "no"}}}, api.RestartPolicyNever}, + "'restart' is set to 'on-failure'": {kobject.KomposeObject{ServiceConfigs: map[string]kobject.ServiceConfig{"app": kobject.ServiceConfig{Image: "foobar", Restart: "on-failure"}}}, api.RestartPolicyOnFailure}, + } + + for name, test := range testCases { + t.Log("Test Case:", name) + + objs := k.Transform(test.svc, opt) + + if len(objs) != 1 { + t.Errorf("Expected only one pod, more elements generated.") + } + + for _, obj := range objs { + if pod, ok := obj.(*api.Pod); ok { + + if pod.Spec.RestartPolicy != test.restartPolicy { + t.Errorf("Expected restartPolicy as %s, got %#v", test.restartPolicy, pod.Spec.RestartPolicy) + } + } else { + t.Errorf("Expected 'pod' object not found one") + } + } + } +} diff --git a/pkg/transformer/openshift/openshift.go b/pkg/transformer/openshift/openshift.go index 0bdb3200..b71358b7 100644 --- a/pkg/transformer/openshift/openshift.go +++ b/pkg/transformer/openshift/openshift.go @@ -155,20 +155,27 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C var allobjects []runtime.Object for name, service := range komposeObject.ServiceConfigs { - objects := o.CreateKubernetesObjects(name, service, opt) + var objects []runtime.Object - if opt.CreateDeploymentConfig { - objects = append(objects, o.initDeploymentConfig(name, service, opt.Replicas)) // OpenShift DeploymentConfigs - // create ImageStream after deployment (creating IS will trigger new deployment) - objects = append(objects, o.initImageStream(name, service)) + // Generate pod only and nothing more + if service.Restart == "no" || service.Restart == "on-failure" { + pod := o.InitPod(name, service) + objects = append(objects, pod) + } else { + objects = o.CreateKubernetesObjects(name, service, opt) + + if opt.CreateDeploymentConfig { + objects = append(objects, o.initDeploymentConfig(name, service, opt.Replicas)) // OpenShift DeploymentConfigs + // create ImageStream after deployment (creating IS will trigger new deployment) + objects = append(objects, o.initImageStream(name, service)) + } + + // If ports not provided in configuration we will not make service + if o.PortsExist(name, service) { + svc := o.CreateService(name, service, objects) + objects = append(objects, svc) + } } - - // If ports not provided in configuration we will not make service - if o.PortsExist(name, service) { - svc := o.CreateService(name, service, objects) - objects = append(objects, svc) - } - o.UpdateKubernetesObjects(name, service, &objects) allobjects = append(allobjects, objects...) diff --git a/script/test/cmd/tests.sh b/script/test/cmd/tests.sh index 71654471..9ff0230d 100755 --- a/script/test/cmd/tests.sh +++ b/script/test/cmd/tests.sh @@ -103,4 +103,14 @@ convert::expect_success "kompose --bundle $KOMPOSE_ROOT/script/test/fixtures/bun # Test related to kompose --bundle convert to ensure that DSB bundles are converted properly convert::expect_success_and_warning "kompose --bundle $KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/docker-voting-bundle.dsb convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/output-k8s.json" "Service cannot be created because of missing port." + +###### +# Test related to restart options in docker-compose +# kubernetes test +convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/restart-options/docker-compose-restart-no.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/restart-options/output-k8s-restart-no.json" +convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/restart-options/docker-compose-restart-onfail.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/restart-options/output-k8s-restart-onfail.json" +# openshift test +convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/restart-options/docker-compose-restart-no.yml --provider openshift convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/restart-options/output-os-restart-no.json" +convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/restart-options/docker-compose-restart-onfail.yml --provider openshift convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/restart-options/output-os-restart-onfail.json" + exit $EXIT_STATUS diff --git a/script/test/fixtures/restart-options/docker-compose-restart-no.yml b/script/test/fixtures/restart-options/docker-compose-restart-no.yml new file mode 100644 index 00000000..44fb71da --- /dev/null +++ b/script/test/fixtures/restart-options/docker-compose-restart-no.yml @@ -0,0 +1,9 @@ +version: "2" + +services: + foo: + image: "foobar" + restart: "no" + environment: + GITHUB: surajssd + diff --git a/script/test/fixtures/restart-options/docker-compose-restart-onfail.yml b/script/test/fixtures/restart-options/docker-compose-restart-onfail.yml new file mode 100644 index 00000000..4978a3ac --- /dev/null +++ b/script/test/fixtures/restart-options/docker-compose-restart-onfail.yml @@ -0,0 +1,9 @@ +version: "2" + +services: + foo: + image: "foobar" + restart: "on-failure" + environment: + GITHUB: surajssd + diff --git a/script/test/fixtures/restart-options/output-k8s-restart-no.json b/script/test/fixtures/restart-options/output-k8s-restart-no.json new file mode 100644 index 00000000..dc307318 --- /dev/null +++ b/script/test/fixtures/restart-options/output-k8s-restart-no.json @@ -0,0 +1,35 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": {}, + "items": [ + { + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "foo", + "creationTimestamp": null, + "labels": { + "service": "foo" + } + }, + "spec": { + "containers": [ + { + "name": "foo", + "image": "foobar", + "env": [ + { + "name": "GITHUB", + "value": "surajssd" + } + ], + "resources": {} + } + ], + "restartPolicy": "Never" + }, + "status": {} + } + ] +} diff --git a/script/test/fixtures/restart-options/output-k8s-restart-onfail.json b/script/test/fixtures/restart-options/output-k8s-restart-onfail.json new file mode 100644 index 00000000..e7748763 --- /dev/null +++ b/script/test/fixtures/restart-options/output-k8s-restart-onfail.json @@ -0,0 +1,35 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": {}, + "items": [ + { + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "foo", + "creationTimestamp": null, + "labels": { + "service": "foo" + } + }, + "spec": { + "containers": [ + { + "name": "foo", + "image": "foobar", + "env": [ + { + "name": "GITHUB", + "value": "surajssd" + } + ], + "resources": {} + } + ], + "restartPolicy": "OnFailure" + }, + "status": {} + } + ] +} diff --git a/script/test/fixtures/restart-options/output-os-restart-no.json b/script/test/fixtures/restart-options/output-os-restart-no.json new file mode 100644 index 00000000..dc307318 --- /dev/null +++ b/script/test/fixtures/restart-options/output-os-restart-no.json @@ -0,0 +1,35 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": {}, + "items": [ + { + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "foo", + "creationTimestamp": null, + "labels": { + "service": "foo" + } + }, + "spec": { + "containers": [ + { + "name": "foo", + "image": "foobar", + "env": [ + { + "name": "GITHUB", + "value": "surajssd" + } + ], + "resources": {} + } + ], + "restartPolicy": "Never" + }, + "status": {} + } + ] +} diff --git a/script/test/fixtures/restart-options/output-os-restart-onfail.json b/script/test/fixtures/restart-options/output-os-restart-onfail.json new file mode 100644 index 00000000..e7748763 --- /dev/null +++ b/script/test/fixtures/restart-options/output-os-restart-onfail.json @@ -0,0 +1,35 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": {}, + "items": [ + { + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "foo", + "creationTimestamp": null, + "labels": { + "service": "foo" + } + }, + "spec": { + "containers": [ + { + "name": "foo", + "image": "foobar", + "env": [ + { + "name": "GITHUB", + "value": "surajssd" + } + ], + "resources": {} + } + ], + "restartPolicy": "OnFailure" + }, + "status": {} + } + ] +}