From 163f4a5d322352bd98f9a88ebd6089cf5e5b49ad Mon Sep 17 00:00:00 2001 From: Saravanan Balasubramanian <33908564+sarabala1979@users.noreply.github.com> Date: Thu, 30 May 2019 16:42:40 -0700 Subject: [PATCH] Fixed: Support hostAliases in WorkflowSpec #1265 (#1365) * Fixed : Support hostAliases in WorkflowSpec #1265 --- api/openapi-spec/swagger.json | 14 +++++++++ .../workflow/v1alpha1/openapi_generated.go | 30 +++++++++++++++++-- pkg/apis/workflow/v1alpha1/types.go | 6 ++++ .../v1alpha1/zz_generated.deepcopy.go | 14 +++++++++ .../template_level_host_aliases.yaml | 17 +++++++++++ .../workflow_level_host_aliases.yaml | 16 ++++++++++ ...workflow_teemplate_level_host_aliases.yaml | 21 +++++++++++++ workflow/controller/workflowpod.go | 5 ++++ workflow/controller/workflowpod_test.go | 30 +++++++++++++++++++ 9 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 test/e2e/functional/template_level_host_aliases.yaml create mode 100644 test/e2e/functional/workflow_level_host_aliases.yaml create mode 100644 test/e2e/functional/workflow_teemplate_level_host_aliases.yaml diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index dc762fb3d751..010feb6d19f0 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -825,6 +825,13 @@ "description": "DAG template subtype which runs a DAG", "$ref": "#/definitions/io.argoproj.workflow.v1alpha1.DAGTemplate" }, + "hostAliases": { + "description": "HostAliases is an optional list of hosts and IPs that will be injected into the pod spec", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.HostAlias" + } + }, "initContainers": { "description": "InitContainers is a list of containers which run before the main container.", "type": "array", @@ -1153,6 +1160,13 @@ "description": "Entrypoint is a template reference to the starting point of the workflow", "type": "string" }, + "hostAliases": { + "description": "HostAliases is an optional list of hosts and IPs that will be injected into the pod spec", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.HostAlias" + } + }, "hostNetwork": { "description": "Host networking requested for this workflow pod. Default to false.", "type": "boolean" diff --git a/pkg/apis/workflow/v1alpha1/openapi_generated.go b/pkg/apis/workflow/v1alpha1/openapi_generated.go index 6aa073d0e19b..392818bd5a32 100644 --- a/pkg/apis/workflow/v1alpha1/openapi_generated.go +++ b/pkg/apis/workflow/v1alpha1/openapi_generated.go @@ -1696,12 +1696,25 @@ func schema_pkg_apis_workflow_v1alpha1_Template(ref common.ReferenceCallback) co Format: "int32", }, }, + "hostAliases": { + SchemaProps: spec.SchemaProps{ + Description: "HostAliases is an optional list of hosts and IPs that will be injected into the pod spec", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.HostAlias"), + }, + }, + }, + }, + }, }, Required: []string{"name"}, }, }, Dependencies: []string{ - "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.ArtifactLocation", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.DAGTemplate", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Inputs", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Metadata", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Outputs", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.ResourceTemplate", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.RetryStrategy", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.ScriptTemplate", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.SuspendTemplate", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.UserContainer", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.WorkflowStep", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume"}, + "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.ArtifactLocation", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.DAGTemplate", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Inputs", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Metadata", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Outputs", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.ResourceTemplate", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.RetryStrategy", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.ScriptTemplate", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.SuspendTemplate", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.UserContainer", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.WorkflowStep", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume"}, } } @@ -2262,12 +2275,25 @@ func schema_pkg_apis_workflow_v1alpha1_WorkflowSpec(ref common.ReferenceCallback Format: "int32", }, }, + "hostAliases": { + SchemaProps: spec.SchemaProps{ + Description: "HostAliases is an optional list of hosts and IPs that will be injected into the pod spec", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.HostAlias"), + }, + }, + }, + }, + }, }, Required: []string{"templates", "entrypoint"}, }, }, Dependencies: []string{ - "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Arguments", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Template", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PersistentVolumeClaim", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume"}, + "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Arguments", "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1.Template", "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PersistentVolumeClaim", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.Volume"}, } } diff --git a/pkg/apis/workflow/v1alpha1/types.go b/pkg/apis/workflow/v1alpha1/types.go index 9e1ca64e2ffd..f5d35003437a 100644 --- a/pkg/apis/workflow/v1alpha1/types.go +++ b/pkg/apis/workflow/v1alpha1/types.go @@ -164,6 +164,9 @@ type WorkflowSpec struct { // Priority to apply to workflow pods. PodPriority *int32 `json:"podPriority,omitempty"` + + // HostAliases is an optional list of hosts and IPs that will be injected into the pod spec + HostAliases []apiv1.HostAlias `json:"hostAliases,omitempty"` } // Template is a reusable and composable unit of execution in a workflow @@ -252,6 +255,9 @@ type Template struct { // Priority to apply to workflow pods. Priority *int32 `json:"priority,omitempty"` + + // HostAliases is an optional list of hosts and IPs that will be injected into the pod spec + HostAliases []apiv1.HostAlias `json:"hostAliases,omitempty"` } // Inputs are the mechanism for passing parameters, artifacts, volumes from one template to another diff --git a/pkg/apis/workflow/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/workflow/v1alpha1/zz_generated.deepcopy.go index 9bd20892eb6b..48f38e70c121 100644 --- a/pkg/apis/workflow/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/workflow/v1alpha1/zz_generated.deepcopy.go @@ -848,6 +848,13 @@ func (in *Template) DeepCopyInto(out *Template) { *out = new(int32) **out = **in } + if in.HostAliases != nil { + in, out := &in.HostAliases, &out.HostAliases + *out = make([]v1.HostAlias, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -1054,6 +1061,13 @@ func (in *WorkflowSpec) DeepCopyInto(out *WorkflowSpec) { *out = new(int32) **out = **in } + if in.HostAliases != nil { + in, out := &in.HostAliases, &out.HostAliases + *out = make([]v1.HostAlias, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/test/e2e/functional/template_level_host_aliases.yaml b/test/e2e/functional/template_level_host_aliases.yaml new file mode 100644 index 000000000000..49cd6ab6c53f --- /dev/null +++ b/test/e2e/functional/template_level_host_aliases.yaml @@ -0,0 +1,17 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: template-level-host-aliases- +spec: + entrypoint: nslookup + + templates: + - name: nslookup + hostAliases: + - ip: "127.0.0.1" + hostnames: + - "argo.io" + container: + image: alpine:latest + command: [sh, -c] + args: [" nslookup argo.io"] \ No newline at end of file diff --git a/test/e2e/functional/workflow_level_host_aliases.yaml b/test/e2e/functional/workflow_level_host_aliases.yaml new file mode 100644 index 000000000000..d7080d73af0d --- /dev/null +++ b/test/e2e/functional/workflow_level_host_aliases.yaml @@ -0,0 +1,16 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: workflow_level_host_aliases- +spec: + entrypoint: nslookup + hostAliases: + - ip: "127.0.0.1" + hostnames: + - "argo.io" + templates: + - name: nslookup + container: + image: alpine:latest + command: [sh, -c] + args: ["nslookup argo.io"] \ No newline at end of file diff --git a/test/e2e/functional/workflow_teemplate_level_host_aliases.yaml b/test/e2e/functional/workflow_teemplate_level_host_aliases.yaml new file mode 100644 index 000000000000..9768b28c679c --- /dev/null +++ b/test/e2e/functional/workflow_teemplate_level_host_aliases.yaml @@ -0,0 +1,21 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: workflow-template-level-host-aliases- +spec: + entrypoint: nslookup + hostAliases: + - ip: "127.0.0.1" + hostnames: + - "argo.io" + + templates: + - name: nslookup + hostAliases: + - ip: "124.0.0.1" + hostnames: + - "argo1.io" + container: + image: alpine:latest + command: [sh, -c] + args: ["nslookup argo.io argo1.io "] \ No newline at end of file diff --git a/workflow/controller/workflowpod.go b/workflow/controller/workflowpod.go index 3c4630d0c21d..94055dc279d4 100644 --- a/workflow/controller/workflowpod.go +++ b/workflow/controller/workflowpod.go @@ -488,6 +488,11 @@ func addSchedulingConstraints(pod *apiv1.Pod, wfSpec *wfv1.WorkflowSpec, tmpl *w } else if wfSpec.SchedulerName != "" { pod.Spec.SchedulerName = wfSpec.SchedulerName } + + // set hostaliases + pod.Spec.HostAliases = append(pod.Spec.HostAliases, wfSpec.HostAliases...) + pod.Spec.HostAliases = append(pod.Spec.HostAliases, tmpl.HostAliases...) + } // addVolumeReferences adds any volumeMounts that a container/sidecar is referencing, to the pod.spec.volumes diff --git a/workflow/controller/workflowpod_test.go b/workflow/controller/workflowpod_test.go index 9884ecae2763..d4a7f73db66e 100644 --- a/workflow/controller/workflowpod_test.go +++ b/workflow/controller/workflowpod_test.go @@ -612,3 +612,33 @@ func TestTemplateLocalVolumes(t *testing.T) { assert.Contains(t, pod.Spec.Volumes, v) } } + +// TestWFLevelHostAliases verifies the ability to carry forward workflow level HostAliases to Podspec +func TestWFLevelHostAliases(t *testing.T) { + woc := newWoc() + woc.wf.Spec.HostAliases = []apiv1.HostAlias{ + {IP: "127.0.0.1"}, + {IP: "127.0.0.1"}, + } + woc.executeContainer(woc.wf.Spec.Entrypoint, &woc.wf.Spec.Templates[0], "") + podName := getPodName(woc.wf) + pod, err := woc.controller.kubeclientset.CoreV1().Pods("").Get(podName, metav1.GetOptions{}) + assert.Nil(t, err) + assert.NotNil(t, pod.Spec.HostAliases) + +} + +// TestTmplLevelHostAliases verifies the ability to carry forward template level HostAliases to Podspec +func TestTmplLevelHostAliases(t *testing.T) { + woc := newWoc() + woc.wf.Spec.Templates[0].HostAliases = []apiv1.HostAlias{ + {IP: "127.0.0.1"}, + {IP: "127.0.0.1"}, + } + woc.executeContainer(woc.wf.Spec.Entrypoint, &woc.wf.Spec.Templates[0], "") + podName := getPodName(woc.wf) + pod, err := woc.controller.kubeclientset.CoreV1().Pods("").Get(podName, metav1.GetOptions{}) + assert.Nil(t, err) + assert.NotNil(t, pod.Spec.HostAliases) + +}