Skip to content

Commit

Permalink
Add template for imagePullPolicy checks (#202)
Browse files Browse the repository at this point in the history
  • Loading branch information
glehmann authored Aug 20, 2021
1 parent 6c2c830 commit e01d3c4
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 1 deletion.
24 changes: 24 additions & 0 deletions docs/generated/templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,30 @@ KubeLinter supports the following templates:
[]
```

## Image Pull Policy

**Key**: `image-pull-policy`

**Description**: Flag containers with forbidden image pull policy

**Supported Objects**: DeploymentLike

**Parameters**:

```json
[
{
"name": "forbiddenPolicies",
"type": "array",
"description": "list of forbidden image pull policy",
"required": false,
"regexAllowed": false,
"negationAllowed": false,
"arrayElemType": "string"
}
]
```

## Latest Tag

**Key**: `latest-tag`
Expand Down
1 change: 1 addition & 0 deletions pkg/templates/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
_ "golang.stackrox.io/kube-linter/pkg/templates/hostmounts"
_ "golang.stackrox.io/kube-linter/pkg/templates/hostnetwork"
_ "golang.stackrox.io/kube-linter/pkg/templates/hostpid"
_ "golang.stackrox.io/kube-linter/pkg/templates/imagepullpolicy"
_ "golang.stackrox.io/kube-linter/pkg/templates/latesttag"
_ "golang.stackrox.io/kube-linter/pkg/templates/livenessprobe"
_ "golang.stackrox.io/kube-linter/pkg/templates/memoryrequirements"
Expand Down
21 changes: 20 additions & 1 deletion pkg/templates/codegen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ var (
func (p *Params) Validate() error {
var validationErrors []string
{{- range . }}
{{- if eq .ParamDesc.Type "object" }}
{{- if eq .ParamDesc.Type "object" }}
return errors.Errorf("parameter validation not yet supported for object type \"{{ .ParamDesc.Key }}\"")
{{- end }}
{{- if .ParamDesc.Required }}
Expand All @@ -85,6 +85,24 @@ func (p *Params) Validate() error {
}
{{- end }}
{{- if .ParamDesc.Enum }}
{{- if eq .ParamDesc.Type "array" }}
for _, value := range p.{{ .ParamDesc.XXXStructFieldName }} {
var found bool
for _, allowedValue := range []string{
{{- range .ParamDesc.Enum }}
"{{ . }}",
{{- end }}
}{
if value == allowedValue {
found = true
break
}
}
if !found {
validationErrors = append(validationErrors, fmt.Sprintf("param {{ .ParamDesc.Name }} has invalid value %q, must be one of {{ .ParamDesc.Enum }}", p.{{ .ParamDesc.XXXStructFieldName }}))
}
}
{{- else }}
var found bool
for _, allowedValue := range []string{
{{- range .ParamDesc.Enum }}
Expand All @@ -101,6 +119,7 @@ func (p *Params) Validate() error {
}
{{- end }}
{{- end }}
{{- end }}
if len(validationErrors) > 0 {
return errors.Errorf("invalid parameters: %s", strings.Join(validationErrors, ", "))
}
Expand Down
89 changes: 89 additions & 0 deletions pkg/templates/imagepullpolicy/internal/params/gen-params.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions pkg/templates/imagepullpolicy/internal/params/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package params

// Params represents the params accepted by this template.
type Params struct {
// list of forbidden image pull policy
// +noregex
// +notnegatable
// +enum=Always
// +enum=IfNotPresent
// +enum=Never
ForbiddenPolicies []string
}
41 changes: 41 additions & 0 deletions pkg/templates/imagepullpolicy/template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package imagepullpolicy

import (
"fmt"

"golang.stackrox.io/kube-linter/internal/set"
"golang.stackrox.io/kube-linter/pkg/check"
"golang.stackrox.io/kube-linter/pkg/config"
"golang.stackrox.io/kube-linter/pkg/diagnostic"
"golang.stackrox.io/kube-linter/pkg/objectkinds"
"golang.stackrox.io/kube-linter/pkg/templates"
"golang.stackrox.io/kube-linter/pkg/templates/imagepullpolicy/internal/params"
"golang.stackrox.io/kube-linter/pkg/templates/util"
v1 "k8s.io/api/core/v1"
)

const (
templateKey = "image-pull-policy"
)

func init() {
templates.Register(check.Template{
HumanName: "Image Pull Policy",
Key: templateKey,
Description: "Flag containers with forbidden image pull policy",
SupportedObjectKinds: config.ObjectKindsDesc{
ObjectKinds: []string{objectkinds.DeploymentLike},
},
Parameters: params.ParamDescs,
ParseAndValidateParams: params.ParseAndValidate,
Instantiate: params.WrapInstantiateFunc(func(p params.Params) (check.Func, error) {
forbiddenPolicies := set.NewStringSet(p.ForbiddenPolicies...)
return util.PerContainerCheck(func(container *v1.Container) []diagnostic.Diagnostic {
if forbiddenPolicies.Contains(string(container.ImagePullPolicy)) {
return []diagnostic.Diagnostic{{Message: fmt.Sprintf("container %q has imagePullPolicy set to %s", container.Name, container.ImagePullPolicy)}}
}
return nil
}), nil
}),
})
}
59 changes: 59 additions & 0 deletions pkg/templates/imagepullpolicy/template_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package imagepullpolicy

import (
"testing"

"github.com/stretchr/testify/suite"

"golang.stackrox.io/kube-linter/pkg/diagnostic"
"golang.stackrox.io/kube-linter/pkg/lintcontext/mocks"
"golang.stackrox.io/kube-linter/pkg/templates"
"golang.stackrox.io/kube-linter/pkg/templates/imagepullpolicy/internal/params"

v1 "k8s.io/api/core/v1"
)

func TestContainerImage(t *testing.T) {
suite.Run(t, new(ContainerImageTestSuite))
}

type ContainerImageTestSuite struct {
templates.TemplateTestSuite
ctx *mocks.MockLintContext
}

func (s *ContainerImageTestSuite) SetupTest() {
s.Init(templateKey)
s.ctx = mocks.NewMockContext()
}

func (s *ContainerImageTestSuite) addDeploymentWithContainerImage(name string, pullPolicy v1.PullPolicy) {
s.ctx.AddMockDeployment(s.T(), name)
s.ctx.AddContainerToDeployment(s.T(), name, v1.Container{Name: "test-container", ImagePullPolicy: pullPolicy})
}

func (s *ContainerImageTestSuite) TestImaPolicy() {
const (
alwaysDep = "deployment-with-always-pull-policy"
ifNotPresentDep = "deployment-with-if-not-present-pull-policy"
neverDep = "deployment-with-never-pull-policy"
)

s.addDeploymentWithContainerImage(alwaysDep, v1.PullAlways)
s.addDeploymentWithContainerImage(ifNotPresentDep, v1.PullIfNotPresent)
s.addDeploymentWithContainerImage(neverDep, v1.PullNever)

s.Validate(s.ctx, []templates.TestCase{
{
Param: params.Params{
ForbiddenPolicies: []string{"Always"},
},
Diagnostics: map[string][]diagnostic.Diagnostic{
alwaysDep: {
{Message: "container \"test-container\" has imagePullPolicy set to Always"},
},
},
ExpectInstantiationError: false,
},
})
}

0 comments on commit e01d3c4

Please sign in to comment.