Skip to content

Commit

Permalink
Merge pull request #85 from doitintl/feat-replace-since
Browse files Browse the repository at this point in the history
Feat replace since
  • Loading branch information
stepanstipl authored Dec 31, 2020
2 parents 86a8eb8 + 4891f3e commit e6d96a5
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ $(RELEASE_DIR)/%-$(RELEASE_SUFFIX): $(PACKED_DIR)/%-$(BIN_ARCH)

## Run Go tests
test: generate test-fmt test-git
go test -coverprofile fmtcoverage.html ./...
go test -v -coverprofile fmtcoverage.html ./...
.PHONY: test

## Run go and opt fmt checks
Expand Down
14 changes: 14 additions & 0 deletions fixtures/ingress-v1beta1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /testpath
backend:
serviceName: test
servicePort: 80
2 changes: 1 addition & 1 deletion generated/statik/statik.go

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

12 changes: 7 additions & 5 deletions pkg/judge/judge.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package judge

type Result struct {
Name string
Namespace string
Kind string
ApiVersion string
RuleSet string
Name string
Namespace string
Kind string
ApiVersion string
RuleSet string
ReplaceWith string
Since string
}

type Judge interface {
Expand Down
12 changes: 7 additions & 5 deletions pkg/judge/rego.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,13 @@ func (j *RegoJudge) Eval(input []map[string]interface{}) ([]Result, error) {
for _, i := range e.Value.([]interface{}) {
m := i.(map[string]interface{})
results = append(results, Result{
Name: m["Name"].(string),
Namespace: m["Namespace"].(string),
Kind: m["Kind"].(string),
ApiVersion: m["ApiVersion"].(string),
RuleSet: m["RuleSet"].(string),
Name: m["Name"].(string),
Namespace: m["Namespace"].(string),
Kind: m["Kind"].(string),
ApiVersion: m["ApiVersion"].(string),
ReplaceWith: m["ReplaceWith"].(string),
RuleSet: m["RuleSet"].(string),
Since: m["Since"].(string),
})
}
}
Expand Down
66 changes: 66 additions & 0 deletions pkg/judge/rego_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
package judge

import (
"github.com/ghodss/yaml"
"io/ioutil"
"testing"
)

func TestNewRegoJudge(t *testing.T) {
_, err := NewRegoJudge(&RegoOpts{})
if err != nil {
t.Errorf("failed to create judge instance: %s", err)
}
}

func TestEvalEmpty(t *testing.T) {
inputs := []map[string]interface{}{}

Expand All @@ -21,3 +30,60 @@ func TestEvalEmpty(t *testing.T) {
t.Errorf("expected empty array, instead got: %v", results)
}
}

func TestEvalRules(t *testing.T) {
testCases := []struct {
name string
inputFiles []string // file list
expected []string // findings - kinds
}{
{"deprecated-1-16.rego", []string{"../../fixtures/deployment-v1beta1.yaml"}, []string{"Deployment"}},
{"deprecated-1-22.rego", []string{"../../fixtures/ingress-v1beta1.yaml"}, []string{"Ingress"}},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {

var manifests []map[string]interface{}

for _, f := range tc.inputFiles {
var input []byte
var err error

input, err = ioutil.ReadFile(f)
if err != nil {
t.Errorf("failed to read file %s: %v", f, err)
}

var manifest map[string]interface{}
err = yaml.Unmarshal([]byte(input), &manifest)
if err != nil {
t.Errorf("failed to parse file %s: %v", f, err)
}

manifests = append(manifests, manifest)
}

judge, err := NewRegoJudge(&RegoOpts{})
if err != nil {
t.Errorf("failed to create judge instance: %s", err)
}

results, err := judge.Eval(manifests)
if err != nil {
t.Errorf("failed to evaluate input: %s", err)
}

if len(results) != len(tc.expected) {
t.Errorf("expected %d findings, instead got: %d", len(tc.expected), len(results))
}

for i, _ := range results {
if results[i].Kind != tc.expected[i] {
t.Errorf("expected to get %s finding, instead got: %s", tc.expected[i], results[i].Kind)
}
}
})
}

}
4 changes: 2 additions & 2 deletions pkg/printer/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ func (c *TextPrinter) Print(results []judge.Result) error {
fmt.Fprintf(w, "%s\n", strings.Repeat("_", 90))
fmt.Fprintf(w, ">>> %s <<<\n", ruleSet)
fmt.Fprintf(w, "%s\n", strings.Repeat("-", 90))
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t\n", "KIND", "NAMESPACE", "NAME", "API_VERSION")
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s (%s)\n", "KIND", "NAMESPACE", "NAME", "API_VERSION", "REPLACE_WITH", "SINCE")
}
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t\n", r.Kind, r.Namespace, r.Name, r.ApiVersion)
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s (%s+)\n", r.Kind, r.Namespace, r.Name, r.ApiVersion, r.ReplaceWith, r.Since)
}
w.Flush()
return nil
Expand Down
61 changes: 43 additions & 18 deletions rules/deprecated-1-16.rego
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,63 @@ package deprecated116

main[return] {
resource := input[_]
old_api := deprecated_resource(resource)
api := deprecated_resource(resource)
return := {
"Name": resource.metadata.name,
# Namespace does not have to be defined in case of local manifests
"Namespace": get_default(resource.metadata, "namespace", "<undefined>"),
"Kind": resource.kind,
"ApiVersion": old_api,
"ApiVersion": api.old,
"ReplaceWith": api.new,
"RuleSet": "Deprecated APIs removed in 1.16",
"Since": api.since,
}
}

deprecated_resource(r) = old_api {
old_api := deprecated_api(r.kind, r.apiVersion)
deprecated_resource(r) = api {
api := deprecated_api(r.kind, r.apiVersion)
}

deprecated_api(kind, api_version) = old_api {
deprecated_api(kind, api_version) = api {
deprecated_apis = {
"Deployment": ["extensions/v1beta1", "apps/v1beta1", "apps/v1beta2"], # -> apps/v1
# -> networking.k8s.io/v1
"NetworkPolicy": ["extensions/v1beta1"],
# -> policy/v1beta1
"PodSecurityPolicy": ["extensions/v1beta1"],
# -> apps/v1
"DaemonSet": ["extensions/v1beta1", "apps/v1beta2"],
# -> apps/v1
"StatefulSet": ["apps/v1beta1", "apps/v1beta2"],
# -> apps/v1
"ReplicaSet": ["extensions/v1beta1", "apps/v1beta1", "apps/v1beta2"],
"Deployment": {
"old": ["extensions/v1beta1", "apps/v1beta1", "apps/v1beta2"],
"new": "apps/v1",
"since": "1.9",
},
"NetworkPolicy": {
"old": ["extensions/v1beta1"],
"new": "networking.k8s.io/v1",
"since": "1.8",
},
"PodSecurityPolicy": {
"old": ["extensions/v1beta1"],
"new": "policy/v1beta1",
"since": "1.10",
},
"DaemonSet": {
"old": ["extensions/v1beta1", "apps/v1beta2"],
"new": "apps/v1",
"since": "1.9",
},
"StatefulSet": {
"old": ["apps/v1beta1", "apps/v1beta2"],
"new": "apps/v1",
"since": "1.9",
},
"ReplicaSet": {
"old": ["extensions/v1beta1", "apps/v1beta1", "apps/v1beta2"],
"new": "apps/v1",
"since": "1.9",
},
}

deprecated_apis[kind][_] == api_version
old_api := api_version
deprecated_apis[kind].old[_] == api_version
api := {
"old": api_version,
"new": deprecated_apis[kind].new,
"since": deprecated_apis[kind].since,
}
}

get_default(val, key, _) = val[key]
Expand Down
27 changes: 19 additions & 8 deletions rules/deprecated-1-22.rego
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,37 @@ package deprecated120

main[return] {
resource := input[_]
old_api := deprecated_resource(resource)
api := deprecated_resource(resource)
return := {
"Name": resource.metadata.name,
# Namespace does not have to be defined in case of local manifests
"Namespace": get_default(resource.metadata, "namespace", "<undefined>"),
"Kind": resource.kind,
"ApiVersion": old_api,
"ApiVersion": api.old,
"ReplaceWith": api.new,
"RuleSet": "Deprecated APIs removed in 1.22",
"Since": api.since,
}
}

deprecated_resource(r) = old_api {
old_api := deprecated_api(r.kind, r.apiVersion)
deprecated_resource(r) = api {
api := deprecated_api(r.kind, r.apiVersion)
}

deprecated_api(kind, api_version) = old_api {
deprecated_apis = {"Ingress": ["extensions/v1beta1"]} # -> networking.k8s.io/v1beta1
deprecated_api(kind, api_version) = api {
deprecated_apis = {"Ingress": {
"old": ["extensions/v1beta1"],
"new": "networking.k8s.io/v1beta1",
"since": "1.14",
}}

deprecated_apis[kind][_] == api_version
old_api := api_version
deprecated_apis[kind].old[_] == api_version

api := {
"old": api_version,
"new": deprecated_apis[kind].new,
"since": deprecated_apis[kind].since,
}
}

get_default(val, key, _) = val[key]
Expand Down

0 comments on commit e6d96a5

Please sign in to comment.