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 }