Skip to content

Commit

Permalink
target: container also populates .Polaris.PodSpec|PodTemplate + a…
Browse files Browse the repository at this point in the history
… new `.Polaris.Container` representing the currently checked container, `GetPodTemplate` serializes data to work around a DeepCopy bug with type int (#812)
  • Loading branch information
ivanfetch-wt authored Jul 29, 2022
1 parent 652b65b commit c3b57bf
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 6 deletions.
1 change: 1 addition & 0 deletions docs/customization/custom-checks.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ schema:
* The object available via the go template is the full object, and not limited by `target`.
* A check of `target: PodSpec` can directly access the pod specification via the go template variable `.Polaris.PodSpec`.
* A check of `target: PodTemplate` can directly access the pod template via the go template variable `.Polaris.PodTemplate`.
* A check of `target: Container` can directly access the container being checked via the go template variable `.Polaris.container`. The pod template and pod specification can also be accessed via the respective variables `.Polaris.PodTemplate` and `.Polaris.PodSpec`. Access to pod-level fields allows a container check to consult related fields from the pod, such as `securityContext`.

You can also use the full [Go template syntax](https://golang.org/pkg/text/template/), though
you may need to specify your schema as a string in order to use concepts like `range`. E.g.
Expand Down
23 changes: 19 additions & 4 deletions pkg/kube/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ func NewGenericResourceFromUnstructured(unst unstructured.Unstructured, podSpecM
return workload, err
}
workload.ObjectMeta = objMeta
workload.PodTemplate = GetPodTemplate(unst.UnstructuredContent())
workload.PodTemplate, err = GetPodTemplate(unst.UnstructuredContent())
if err != nil {
return workload, err
}

b, err := json.Marshal(&unst)
if err != nil {
Expand Down Expand Up @@ -248,11 +251,23 @@ func GetPodSpec(yaml map[string]interface{}) interface{} {
// GetPodTemplate looks inside arbitrary YAML for a Pod template, containing
// fields `spec.containers`.
// For example, it returns the `spec.template` level of a Kubernetes Deployment yaml.
func GetPodTemplate(yaml map[string]interface{}) interface{} {
func GetPodTemplate(yaml map[string]interface{}) (podTemplate interface{}, err error) {
if yamlSpec, ok := yaml["spec"]; ok {
if yamlSpecMap, ok := yamlSpec.(map[string]interface{}); ok {
if _, ok := yamlSpecMap["containers"]; ok {
return yaml
// This is a hack around unstructured.SetNestedField using DeepCopy which does
// not support the type int, and panics.
// Related: https://github.com/kubernetes/kubernetes/issues/62769
podTemplateJSON, err := json.Marshal(yaml)
if err != nil {
return nil, err
}
podTemplateMap := make(map[string]interface{})
err = json.Unmarshal(podTemplateJSON, &podTemplateMap)
if err != nil {
return nil, err
}
return podTemplateMap, nil
}
}
}
Expand All @@ -261,5 +276,5 @@ func GetPodTemplate(yaml map[string]interface{}) interface{} {
return GetPodTemplate(childYaml.(map[string]interface{}))
}
}
return nil
return nil, nil
}
14 changes: 14 additions & 0 deletions pkg/kube/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,3 +509,17 @@ func SerializePod(pod *corev1.Pod) (map[string]interface{}, error) {
}
return podMap, nil
}

// SerializeContainer converts a typed Container into a map[string]interface{}
func SerializeContainer(container *corev1.Container) (map[string]interface{}, error) {
containerJSON, err := json.Marshal(container)
if err != nil {
return nil, err
}
containerMap := make(map[string]interface{})
err = json.Unmarshal(containerJSON, &containerMap)
if err != nil {
return nil, err
}
return containerMap, nil
}
15 changes: 13 additions & 2 deletions pkg/validator/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func getTemplateInput(test schemaTestCase) (map[string]interface{}, error) {
if templateInput == nil {
return nil, nil
}
if test.Target == config.TargetPodSpec {
if test.Target == config.TargetPodSpec || test.Target == config.TargetContainer {
podSpecMap, err := kube.SerializePodSpec(test.Resource.PodSpec)
if err != nil {
return nil, err
Expand All @@ -93,12 +93,23 @@ func getTemplateInput(test schemaTestCase) (map[string]interface{}, error) {
if err != nil {
return nil, err
}
if podTemplateMap, ok := test.Resource.PodTemplate.(map[string]interface{}); ok {
podTemplateMap, ok := test.Resource.PodTemplate.(map[string]interface{})
if ok {
err := unstructured.SetNestedMap(templateInput, podTemplateMap, "Polaris", "PodTemplate")
if err != nil {
return nil, err
}
}
if test.Target == config.TargetContainer {
containerMap, err := kube.SerializeContainer(test.Container)
if err != nil {
return nil, err
}
err = unstructured.SetNestedMap(templateInput, containerMap, "Polaris", "Container")
if err != nil {
return nil, err
}
}
}
return templateInput, nil
}
Expand Down

0 comments on commit c3b57bf

Please sign in to comment.