Skip to content

Commit

Permalink
Merge pull request #245 from FairwindsOps/rb/ctrl-versions
Browse files Browse the repository at this point in the history
Add support for more controller versions
  • Loading branch information
Robert Brennan authored Feb 26, 2020
2 parents 6213291 + d2bb2f1 commit cd002d0
Show file tree
Hide file tree
Showing 16 changed files with 706 additions and 61 deletions.
4 changes: 3 additions & 1 deletion cmd/polaris/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ var webhookCmd = &cobra.Command{
for innerIndex, supportedAPIType := range controllerToScan.ListSupportedAPIVersions() {
webhookName := strings.ToLower(fmt.Sprintf("%s-%d-%d", controllerToScan, index, innerIndex))
hook := fwebhook.NewWebhook(webhookName, mgr, fwebhook.Validator{Config: config}, supportedAPIType)
webhooks = append(webhooks, hook)
if hook != nil {
webhooks = append(webhooks, hook)
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions pkg/config/supportedcontrollers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import (
"strings"

appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1"
appsv1beta2 "k8s.io/api/apps/v1beta2"
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
)
Expand Down Expand Up @@ -103,14 +106,19 @@ func (s SupportedController) ListSupportedAPIVersions() []runtime.Object {
case Deployments:
supportedVersions = []runtime.Object{
&appsv1.Deployment{},
&appsv1beta1.Deployment{},
&appsv1beta2.Deployment{},
}
case StatefulSets:
supportedVersions = []runtime.Object{
&appsv1.StatefulSet{},
&appsv1beta1.StatefulSet{},
&appsv1beta2.StatefulSet{},
}
case DaemonSets:
supportedVersions = []runtime.Object{
&appsv1.DaemonSet{},
&appsv1beta2.DaemonSet{},
}
case Jobs:
supportedVersions = []runtime.Object{
Expand All @@ -119,6 +127,7 @@ func (s SupportedController) ListSupportedAPIVersions() []runtime.Object {
case CronJobs:
supportedVersions = []runtime.Object{
&batchv1beta1.CronJob{},
&batchv2alpha1.CronJob{},
}
case ReplicationControllers:
supportedVersions = []runtime.Object{
Expand Down
194 changes: 172 additions & 22 deletions pkg/kube/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package kube

import (
"bytes"
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
Expand Down Expand Up @@ -77,7 +78,7 @@ func CreateResourceProviderFromPath(directory string) (*ResourceProvider, error)
}
contents, err := ioutil.ReadFile(path)
if err != nil {
logrus.Errorf("Error reading file %v", path)
logrus.Errorf("Error reading file: %v", path)
return err
}
specs := regexp.MustCompile("\n-+\n").Split(string(contents), -1)
Expand Down Expand Up @@ -105,12 +106,12 @@ func CreateResourceProviderFromPath(directory string) (*ResourceProvider, error)
func CreateResourceProviderFromCluster() (*ResourceProvider, error) {
kubeConf, configError := config.GetConfig()
if configError != nil {
logrus.Errorf("Error fetching KubeConfig %v", configError)
logrus.Errorf("Error fetching KubeConfig: %v", configError)
return nil, configError
}
api, err := kubernetes.NewForConfig(kubeConf)
if err != nil {
logrus.Errorf("Error creating Kubernetes client %v", err)
logrus.Errorf("Error creating Kubernetes client: %v", err)
return nil, err
}
return CreateResourceProviderFromAPI(api, kubeConf.Host)
Expand All @@ -121,52 +122,49 @@ func CreateResourceProviderFromAPI(kube kubernetes.Interface, clusterName string
listOpts := metav1.ListOptions{}
serverVersion, err := kube.Discovery().ServerVersion()
if err != nil {
logrus.Errorf("Error fetching Cluster API version %v", err)
logrus.Errorf("Error fetching Cluster API version: %v", err)
return nil, err
}
deploys, err := kube.AppsV1().Deployments("").List(listOpts)
deploys, err := getDeployments(kube)
if err != nil {
logrus.Errorf("Error fetching Deployments %v", err)
return nil, err
}
statefulSets, err := kube.AppsV1().StatefulSets("").List(listOpts)
statefulSets, err := getStatefulSets(kube)
if err != nil {
logrus.Errorf("Error fetching StatefulSets%v", err)
return nil, err
}
daemonSets, err := kube.AppsV1().DaemonSets("").List(listOpts)
cronJobs, err := getCronJobs(kube)
if err != nil {
logrus.Errorf("Error fetching DaemonSets %v", err)
return nil, err
}
jobs, err := kube.BatchV1().Jobs("").List(listOpts)
daemonSets, err := getDaemonSets(kube)
if err != nil {
logrus.Errorf("Error fetching Jobs %v", err)
return nil, err
}
cronJobs, err := kube.BatchV1beta1().CronJobs("").List(listOpts)

jobs, err := kube.BatchV1().Jobs("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching CronJobs %v", err)
logrus.Errorf("Error fetching Jobs: %v", err)
return nil, err
}
replicationControllers, err := kube.CoreV1().ReplicationControllers("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching ReplicationControllers %v", err)
logrus.Errorf("Error fetching ReplicationControllers: %v", err)
return nil, err
}
nodes, err := kube.CoreV1().Nodes().List(listOpts)
if err != nil {
logrus.Errorf("Error fetching Nodes %v", err)
logrus.Errorf("Error fetching Nodes: %v", err)
return nil, err
}
namespaces, err := kube.CoreV1().Namespaces().List(listOpts)
if err != nil {
logrus.Errorf("Error fetching Namespaces %v", err)
logrus.Errorf("Error fetching Namespaces: %v", err)
return nil, err
}
pods, err := kube.CoreV1().Pods("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching Pods %v", err)
logrus.Errorf("Error fetching Pods: %v", err)
return nil, err
}

Expand All @@ -175,11 +173,11 @@ func CreateResourceProviderFromAPI(kube kubernetes.Interface, clusterName string
SourceType: "Cluster",
SourceName: clusterName,
CreationTime: time.Now(),
Deployments: deploys.Items,
StatefulSets: statefulSets.Items,
DaemonSets: daemonSets.Items,
Deployments: deploys,
StatefulSets: statefulSets,
DaemonSets: daemonSets,
CronJobs: cronJobs,
Jobs: jobs.Items,
CronJobs: cronJobs.Items,
ReplicationControllers: replicationControllers.Items,
Nodes: nodes.Items,
Namespaces: namespaces.Items,
Expand Down Expand Up @@ -237,3 +235,155 @@ func addResourceFromString(contents string, resources *ResourceProvider) error {
}
return nil
}

func getDeployments(kube kubernetes.Interface) ([]appsv1.Deployment, error) {
listOpts := metav1.ListOptions{}
deployList, err := kube.AppsV1().Deployments("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching Deployments: %v", err)
return nil, err
}
deploys := deployList.Items

oldDeploys := make([]interface{}, 0)
deploysV1B1, err := kube.AppsV1beta1().Deployments("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching Deployments v1beta1: %v", err)
return nil, err
}
for _, oldDeploy := range deploysV1B1.Items {
oldDeploys = append(oldDeploys, oldDeploy)
}
deploysV1B2, err := kube.AppsV1beta2().Deployments("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching Deployments v1beta2: %v", err)
return nil, err
}
for _, oldDeploy := range deploysV1B2.Items {
oldDeploys = append(oldDeploys, oldDeploy)
}

for _, oldDeploy := range oldDeploys {
str, err := json.Marshal(oldDeploy)
if err != nil {
logrus.Errorf("Error marshaling old deployment version: %v", err)
return nil, err
}
deploy := appsv1.Deployment{}
err = json.Unmarshal(str, &deploy)
if err != nil {
logrus.Errorf("Error unmarshaling old deployment version: %v", err)
return nil, err
}
deploys = append(deploys, deploy)
}
return deploys, nil
}

func getStatefulSets(kube kubernetes.Interface) ([]appsv1.StatefulSet, error) {
listOpts := metav1.ListOptions{}
controllerList, err := kube.AppsV1().StatefulSets("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching StatefulSets: %v", err)
return nil, err
}
controllers := controllerList.Items

oldControllers := make([]interface{}, 0)
controllersV1B1, err := kube.AppsV1beta1().StatefulSets("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching StatefulSets v1beta1: %v", err)
return nil, err
}
for _, oldController := range controllersV1B1.Items {
oldControllers = append(oldControllers, oldController)
}
controllersV1B2, err := kube.AppsV1beta2().StatefulSets("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching StatefulSets v1beta2: %v", err)
return nil, err
}
for _, oldController := range controllersV1B2.Items {
oldControllers = append(oldControllers, oldController)
}

for _, oldController := range oldControllers {
str, err := json.Marshal(oldController)
if err != nil {
logrus.Errorf("Error marshaling old StatefulSet version: %v", err)
return nil, err
}
controller := appsv1.StatefulSet{}
err = json.Unmarshal(str, &controller)
if err != nil {
logrus.Errorf("Error unmarshaling old StatefulSet version: %v", err)
return nil, err
}
controllers = append(controllers, controller)
}
return controllers, nil
}

func getDaemonSets(kube kubernetes.Interface) ([]appsv1.DaemonSet, error) {
listOpts := metav1.ListOptions{}
controllerList, err := kube.AppsV1().DaemonSets("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching DaemonSets: %v", err)
return nil, err
}
controllers := controllerList.Items

controllersV1B2, err := kube.AppsV1beta2().DaemonSets("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching DaemonSets v1beta2: %v", err)
return nil, err
}

for _, oldController := range controllersV1B2.Items {
str, err := json.Marshal(oldController)
if err != nil {
logrus.Errorf("Error marshaling old DaemonSet version: %v", err)
return nil, err
}
controller := appsv1.DaemonSet{}
err = json.Unmarshal(str, &controller)
if err != nil {
logrus.Errorf("Error unmarshaling old DaemonSet version: %v", err)
return nil, err
}
controllers = append(controllers, controller)
}
return controllers, nil
}

func getCronJobs(kube kubernetes.Interface) ([]batchv1beta1.CronJob, error) {
listOpts := metav1.ListOptions{}
controllerList, err := kube.BatchV1beta1().CronJobs("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching CronJobs: %v", err)
return nil, err
}
controllers := controllerList.Items

controllersV2A1, err := kube.BatchV2alpha1().CronJobs("").List(listOpts)
if err != nil {
logrus.Errorf("Error fetching CronJobs v2alpha1: %v", err)
return nil, err
}

for _, oldController := range controllersV2A1.Items {
str, err := json.Marshal(oldController)
if err != nil {
logrus.Errorf("Error marshaling old CronJob version: %v", err)
return nil, err
}
controller := batchv1beta1.CronJob{}
err = json.Unmarshal(str, &controller)
if err != nil {
logrus.Errorf("Error unmarshaling old CronJob version: %v", err)
return nil, err
}
controllers = append(controllers, controller)
}
return controllers, nil
}
51 changes: 25 additions & 26 deletions pkg/validator/fullaudit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
func TestGetTemplateData(t *testing.T) {
k8s := test.SetupTestAPI()
k8s = test.SetupAddControllers(k8s, "test")
k8s = test.SetupAddExtraControllerVersions(k8s, "test-extra")
resources, err := kube.CreateResourceProviderFromAPI(k8s, "test")
assert.Equal(t, err, nil, "error should be nil")

Expand All @@ -32,8 +33,8 @@ func TestGetTemplateData(t *testing.T) {

sum := CountSummary{
Successes: uint(0),
Warnings: uint(4),
Errors: uint(4),
Warnings: uint(9),
Errors: uint(9),
}

actualAudit, err := RunAudit(c, resources)
Expand All @@ -43,29 +44,27 @@ func TestGetTemplateData(t *testing.T) {
assert.Equal(t, actualAudit.SourceType, "Cluster", "should be from a cluster")
assert.Equal(t, actualAudit.SourceName, "test", "should be from a cluster")

assert.Equal(t, 6, len(actualAudit.Results))

assert.Equal(t, "Deployment", actualAudit.Results[0].Kind)
assert.Equal(t, 1, len(actualAudit.Results[0].PodResult.ContainerResults))
assert.Equal(t, 2, len(actualAudit.Results[0].PodResult.ContainerResults[0].Results))

assert.Equal(t, "StatefulSet", actualAudit.Results[1].Kind)
assert.Equal(t, 1, len(actualAudit.Results[1].PodResult.ContainerResults))
assert.Equal(t, 2, len(actualAudit.Results[1].PodResult.ContainerResults[0].Results))

assert.Equal(t, "DaemonSet", actualAudit.Results[2].Kind)
assert.Equal(t, 1, len(actualAudit.Results[2].PodResult.ContainerResults))
assert.Equal(t, 2, len(actualAudit.Results[2].PodResult.ContainerResults[0].Results))

assert.Equal(t, "Job", actualAudit.Results[3].Kind)
assert.Equal(t, 1, len(actualAudit.Results[3].PodResult.ContainerResults))
assert.Equal(t, 0, len(actualAudit.Results[3].PodResult.ContainerResults[0].Results))

assert.Equal(t, "CronJob", actualAudit.Results[4].Kind)
assert.Equal(t, 1, len(actualAudit.Results[4].PodResult.ContainerResults))
assert.Equal(t, 0, len(actualAudit.Results[4].PodResult.ContainerResults[0].Results))
expected := []struct {
kind string
results int
}{
{kind: "Deployment", results: 2},
{kind: "Deployment", results: 2},
{kind: "Deployment", results: 2},
{kind: "StatefulSet", results: 2},
{kind: "StatefulSet", results: 2},
{kind: "StatefulSet", results: 2},
{kind: "DaemonSet", results: 2},
{kind: "DaemonSet", results: 2},
{kind: "Job", results: 0},
{kind: "CronJob", results: 0},
{kind: "ReplicationController", results: 2},
}

assert.Equal(t, "ReplicationController", actualAudit.Results[5].Kind)
assert.Equal(t, 1, len(actualAudit.Results[5].PodResult.ContainerResults))
assert.Equal(t, 2, len(actualAudit.Results[5].PodResult.ContainerResults[0].Results))
assert.Equal(t, len(expected), len(actualAudit.Results))
for idx, result := range actualAudit.Results {
assert.Equal(t, expected[idx].kind, result.Kind)
assert.Equal(t, 1, len(result.PodResult.ContainerResults))
assert.Equal(t, expected[idx].results, len(result.PodResult.ContainerResults[0].Results))
}
}
Loading

0 comments on commit cd002d0

Please sign in to comment.