From d7cfb2cb03b01a5ada279680aed9f5ddc3f2965d Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Mon, 23 Oct 2023 12:16:46 -0700 Subject: [PATCH] Add os tests (#2307) * initial schema * Add expandWindowsSecurityContext Func * add flattener * fix os attribute and tests * add host_process * fix testconfig * remove duplicates * WIP: marked as required despite being optional * add check for os value * update tests and expandOS function --- kubernetes/schema_pod_spec.go | 31 +++++++++++++ kubernetes/structures_pod.go | 85 ++++++++++++++++++++++++++++------- 2 files changed, 100 insertions(+), 16 deletions(-) diff --git a/kubernetes/schema_pod_spec.go b/kubernetes/schema_pod_spec.go index be91d58e24..8d014f0cf0 100644 --- a/kubernetes/schema_pod_spec.go +++ b/kubernetes/schema_pod_spec.go @@ -346,6 +346,37 @@ func podSpecFields(isUpdatable, isComputed bool) map[string]*schema.Schema { Type: schema.TypeInt, }, }, + "windows_options": { + Type: schema.TypeList, + MaxItems: 1, + Description: "The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. Note that this field cannot be set when spec.os.name is linux.", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "gmsa_credential_spec": { + Type: schema.TypeString, + Description: "GMSACredentialSpec is where the GMSA admission webhook inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field", + Optional: true, + }, + "gmsa_credential_spec_name": { + Type: schema.TypeString, + Description: "GMSACredentialSpecName is the name of the GMSA credential spec to use.", + Optional: true, + }, + "host_process": { + Type: schema.TypeBool, + Description: "HostProcess determines if a container should be run as a 'Host Process' container. Default value is false.", + Default: false, + Optional: true, + }, + "run_as_username": { + Type: schema.TypeString, + Description: "The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", + Optional: true, + }, + }, + }, + }, "sysctl": { Type: schema.TypeList, Optional: true, diff --git a/kubernetes/structures_pod.go b/kubernetes/structures_pod.go index 92700fa7f5..df3308d888 100644 --- a/kubernetes/structures_pod.go +++ b/kubernetes/structures_pod.go @@ -250,6 +250,10 @@ func flattenPodSecurityContext(in *v1.PodSecurityContext) []interface{} { att["sysctl"] = flattenSysctls(in.Sysctls) } + if in.WindowsOptions != nil { + att["windows_options"] = flattenWindowsOptions(*in.WindowsOptions) + } + if len(att) > 0 { return []interface{}{att} } @@ -706,21 +710,6 @@ func flattenPodEphemeralVolumeSource(in *v1.EphemeralVolumeSource) []interface{} // Expanders -func expandOS(l []interface{}) *v1.PodOS { - if len(l) == 0 || l[0] == nil { - return nil - } - - in := l[0].(map[string]interface{}) - obj := &v1.PodOS{} - - if v, ok := in["name"].(string); ok { - obj.Name = v1.OSName(v) - } - - return obj -} - func expandPodTargetState(p []interface{}) []string { if len(p) > 0 { t := make([]string, len(p)) @@ -839,7 +828,7 @@ func expandPodSpec(p []interface{}) (*v1.PodSpec, error) { obj.NodeSelector = nodeSelectors } - if v, ok := in["os"].([]interface{}); ok { + if v, ok := in["os"].([]interface{}); ok && len(v) != 0 { obj.OS = expandOS(v) } @@ -914,6 +903,67 @@ func expandPodSpec(p []interface{}) (*v1.PodSpec, error) { return obj, nil } +func expandOS(l []interface{}) *v1.PodOS { + if len(l) == 0 || l[0] == nil { + return nil + } + + in := l[0].(map[string]interface{}) + + return &v1.PodOS{ + Name: v1.OSName(in["name"].(string)), + } +} + +func expandWindowsOptions(l []interface{}) *v1.WindowsSecurityContextOptions { + if len(l) == 0 || l[0] == nil { + return &v1.WindowsSecurityContextOptions{} + } + + in := l[0].(map[string]interface{}) + obj := &v1.WindowsSecurityContextOptions{} + + if v, ok := in["gmsa_credential_spec"].(string); ok { + obj.GMSACredentialSpec = ptrToString(v) + } + + if v, ok := in["host_process"].(bool); ok { + obj.HostProcess = ptrToBool(v) + } + + if v, ok := in["gmsa_credential_spec_name"].(string); ok { + obj.GMSACredentialSpecName = ptrToString(v) + } + + if v, ok := in["run_as_username"].(string); ok { + obj.RunAsUserName = ptrToString(v) + } + + return obj +} + +func flattenWindowsOptions(in v1.WindowsSecurityContextOptions) []interface{} { + att := make(map[string]interface{}) + + if in.GMSACredentialSpec != nil { + att["gmsa_credential_spec"] = *in.GMSACredentialSpec + } + + if in.GMSACredentialSpecName != nil { + att["gmsa_credential_spec_name"] = *in.GMSACredentialSpecName + } + + if in.HostProcess != nil { + att["host_process"] = *in.HostProcess + } + + if in.RunAsUserName != nil { + att["run_as_username"] = *in.RunAsUserName + } + + return []interface{}{att} +} + func expandPodDNSConfig(l []interface{}) (*v1.PodDNSConfig, error) { if len(l) == 0 || l[0] == nil { return &v1.PodDNSConfig{}, nil @@ -1002,6 +1052,9 @@ func expandPodSecurityContext(l []interface{}) (*v1.PodSecurityContext, error) { policy := v1.PodFSGroupChangePolicy(v) obj.FSGroupChangePolicy = &policy } + if v, ok := in["windows_options"].([]interface{}); ok && len(v) > 0 { + obj.WindowsOptions = expandWindowsOptions(v) + } return obj, nil }