diff --git a/pkg/dashboard/templates/dashboard.gohtml b/pkg/dashboard/templates/dashboard.gohtml
index 7b3e85cf..69a6f40b 100644
--- a/pkg/dashboard/templates/dashboard.gohtml
+++ b/pkg/dashboard/templates/dashboard.gohtml
@@ -43,6 +43,10 @@
Pods:
{{.AuditData.ClusterInfo.Pods}}
+
+ Controllers:
+ {{.AuditData.ClusterInfo.Controllers}}
+
Namespaces:
{{.AuditData.ClusterInfo.Namespaces}}
diff --git a/pkg/kube/resources.go b/pkg/kube/resources.go
index 797c77a0..d8413823 100644
--- a/pkg/kube/resources.go
+++ b/pkg/kube/resources.go
@@ -21,7 +21,6 @@ import (
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth" // Required for other auth providers like GKE.
- "k8s.io/client-go/rest"
"k8s.io/client-go/restmapper"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)
@@ -120,11 +119,16 @@ func CreateResourceProviderFromCluster() (*ResourceProvider, error) {
logrus.Errorf("Error creating Kubernetes client: %v", err)
return nil, err
}
- return CreateResourceProviderFromAPI(api, kubeConf.Host, kubeConf)
+ dynamicInterface, err := dynamic.NewForConfig(kubeConf)
+ if err != nil {
+ logrus.Errorf("Error connecting to dynamic interface: %v", err)
+ return nil, err
+ }
+ return CreateResourceProviderFromAPI(api, kubeConf.Host, &dynamicInterface)
}
// CreateResourceProviderFromAPI creates a new ResourceProvider from an existing k8s interface
-func CreateResourceProviderFromAPI(kube kubernetes.Interface, clusterName string, kubeConf *rest.Config) (*ResourceProvider, error) {
+func CreateResourceProviderFromAPI(kube kubernetes.Interface, clusterName string, dynamic *dynamic.Interface) (*ResourceProvider, error) {
listOpts := metav1.ListOptions{}
serverVersion, err := kube.Discovery().ServerVersion()
if err != nil {
@@ -151,11 +155,7 @@ func CreateResourceProviderFromAPI(kube kubernetes.Interface, clusterName string
logrus.Errorf("Error fetching Pods: %v", err)
return nil, err
}
- dynamicInterface, err := dynamic.NewForConfig(kubeConf)
- if err != nil {
- logrus.Errorf("Error connecting to dynamic interface: %v", err)
- return nil, err
- }
+
resources, err := restmapper.GetAPIGroupResources(kube.Discovery())
if err != nil {
logrus.Errorf("Error getting API Group resources: %v", err)
@@ -172,7 +172,7 @@ func CreateResourceProviderFromAPI(kube kubernetes.Interface, clusterName string
Nodes: nodes.Items,
Namespaces: namespaces.Items,
Pods: pods.Items,
- DynamicClient: &dynamicInterface,
+ DynamicClient: dynamic,
RestMapper: &restMapper,
}
return &api, nil
diff --git a/pkg/kube/resources_test.go b/pkg/kube/resources_test.go
index b3326ea4..ee9ccb08 100644
--- a/pkg/kube/resources_test.go
+++ b/pkg/kube/resources_test.go
@@ -62,7 +62,7 @@ func TestGetMultipleResourceFromBadFile(t *testing.T) {
func TestGetResourceFromAPI(t *testing.T) {
k8s := test.SetupTestAPI()
k8s = test.SetupAddControllers(k8s, "test")
- resources, err := CreateResourceProviderFromAPI(k8s, "test")
+ resources, err := CreateResourceProviderFromAPI(k8s, "test", nil)
assert.Equal(t, nil, err, "Error should be nil")
assert.Equal(t, "Cluster", resources.SourceType, "Should have type Path")
@@ -70,9 +70,6 @@ func TestGetResourceFromAPI(t *testing.T) {
assert.IsType(t, time.Now(), resources.CreationTime, "Creation time should be set")
assert.Equal(t, 0, len(resources.Nodes), "Should not have any nodes")
- assert.Equal(t, 1, len(resources.Deployments), "Should have a deployment")
- assert.Equal(t, 1, len(resources.StatefulSets), "Should have a stateful set")
assert.Equal(t, 0, len(resources.Pods), "Should have a pod")
- assert.Equal(t, "", resources.Deployments[0].ObjectMeta.Name)
}
diff --git a/pkg/validator/controller.go b/pkg/validator/controller.go
index dd2c2683..dccd44a0 100644
--- a/pkg/validator/controller.go
+++ b/pkg/validator/controller.go
@@ -103,11 +103,9 @@ func deduplicateControllers(controllerResults []ControllerResult) []ControllerRe
// builds a list of ResourceResults organized by namespace.
func ValidateControllers(config *conf.Configuration, kubeResources *kube.ResourceProvider) ([]ControllerResult, error) {
var controllersToAudit []controller.Interface
- loadedControllers, err := controllers.LoadControllersByKind(conf.NakedPods, kubeResources)
- if err != nil {
- logrus.Warn(err)
- }
+ loadedControllers := controllers.LoadControllers(kubeResources)
controllersToAudit = append(controllersToAudit, loadedControllers...)
+
results := []ControllerResult{}
for _, controller := range controllersToAudit {
if !config.DisallowExemptions && hasExemptionAnnotation(controller) {
@@ -115,10 +113,12 @@ func ValidateControllers(config *conf.Configuration, kubeResources *kube.Resourc
}
result, err := ValidateController(config, controller, kubeResources)
if err != nil {
+ logrus.Warn("An error occured validating controller:", err)
return nil, err
}
results = append(results, result)
}
+
return deduplicateControllers(results), nil
}
diff --git a/pkg/validator/controller_test.go b/pkg/validator/controller_test.go
index e8e832fd..548c2f4f 100644
--- a/pkg/validator/controller_test.go
+++ b/pkg/validator/controller_test.go
@@ -18,7 +18,6 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
conf "github.com/fairwindsops/polaris/pkg/config"
@@ -46,7 +45,7 @@ func TestValidateController(t *testing.T) {
"hostPIDSet": {ID: "hostPIDSet", Message: "Host PID is not configured", Success: true, Severity: "error", Category: "Security"},
}
- actualResult, err := ValidateController(&c, deployment)
+ actualResult, err := ValidateController(&c, deployment, &kube.ResourceProvider{})
if err != nil {
panic(err)
}
@@ -84,7 +83,7 @@ func TestSkipHealthChecks(t *testing.T) {
"readinessProbeMissing": {ID: "readinessProbeMissing", Message: "Readiness probe should be configured", Success: false, Severity: "error", Category: "Health Checks"},
"livenessProbeMissing": {ID: "livenessProbeMissing", Message: "Liveness probe should be configured", Success: false, Severity: "warning", Category: "Health Checks"},
}
- actualResult, err := ValidateController(&c, deployment)
+ actualResult, err := ValidateController(&c, deployment, &kube.ResourceProvider{})
if err != nil {
panic(err)
}
@@ -101,7 +100,7 @@ func TestSkipHealthChecks(t *testing.T) {
Errors: uint(0),
}
expectedResults = ResultSet{}
- actualResult, err = ValidateController(&c, job)
+ actualResult, err = ValidateController(&c, job, &kube.ResourceProvider{})
if err != nil {
panic(err)
}
@@ -117,7 +116,7 @@ func TestSkipHealthChecks(t *testing.T) {
Errors: uint(0),
}
expectedResults = ResultSet{}
- actualResult, err = ValidateController(&c, cronjob)
+ actualResult, err = ValidateController(&c, cronjob, &kube.ResourceProvider{})
if err != nil {
panic(err)
}
@@ -138,7 +137,7 @@ func TestControllerExemptions(t *testing.T) {
},
}
resources := &kube.ResourceProvider{
- Deployments: []appsv1.Deployment{test.MockDeploy()},
+ Pods: []corev1.Pod{test.MockNakedPod()},
}
expectedSum := CountSummary{
@@ -151,10 +150,10 @@ func TestControllerExemptions(t *testing.T) {
panic(err)
}
assert.Equal(t, 1, len(actualResults))
- assert.Equal(t, "Deployment", actualResults[0].Kind)
+ assert.Equal(t, "NakedPod", actualResults[0].Kind)
assert.EqualValues(t, expectedSum, actualResults[0].GetSummary())
- resources.Deployments[0].ObjectMeta.Annotations = map[string]string{
+ resources.Pods[0].ObjectMeta.Annotations = map[string]string{
exemptionAnnotationKey: "true",
}
actualResults, err = ValidateControllers(&c, resources)
diff --git a/pkg/validator/controllers/cronjob.go b/pkg/validator/controllers/cronjob.go
index e55fc485..885ae359 100644
--- a/pkg/validator/controllers/cronjob.go
+++ b/pkg/validator/controllers/cronjob.go
@@ -13,11 +13,6 @@ type CronJobController struct {
K8SResource kubeAPIBatchV1beta1.CronJob
}
-// GetPodTemplate returns the original template spec
-func (c CronJobController) GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec {
- return &c.K8SResource.Spec.JobTemplate.Spec.Template
-}
-
// GetPodSpec returns the original kubernetes template pod spec
func (c CronJobController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &c.K8SResource.Spec.JobTemplate.Spec.Template.Spec
diff --git a/pkg/validator/controllers/daemonset.go b/pkg/validator/controllers/daemonset.go
index a3c67dad..96d8f7d5 100644
--- a/pkg/validator/controllers/daemonset.go
+++ b/pkg/validator/controllers/daemonset.go
@@ -13,11 +13,6 @@ type DaemonSetController struct {
K8SResource kubeAPIAppsV1.DaemonSet
}
-// GetPodTemplate returns the original template spec
-func (d DaemonSetController) GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec {
- return &d.K8SResource.Spec.Template
-}
-
// GetPodSpec returns the original kubernetes template pod spec
func (d DaemonSetController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &d.K8SResource.Spec.Template.Spec
diff --git a/pkg/validator/controllers/deployment.go b/pkg/validator/controllers/deployment.go
index e02a60bd..a2d4d5e9 100644
--- a/pkg/validator/controllers/deployment.go
+++ b/pkg/validator/controllers/deployment.go
@@ -13,11 +13,6 @@ type DeploymentController struct {
K8SResource kubeAPIAppsV1.Deployment
}
-// GetPodTemplate returns the original template spec
-func (d DeploymentController) GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec {
- return &d.K8SResource.Spec.Template
-}
-
// GetPodSpec returns the original kubernetes template pod spec
func (d DeploymentController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &d.K8SResource.Spec.Template.Spec
diff --git a/pkg/validator/controllers/interface.go b/pkg/validator/controllers/interface.go
index f9ee30a7..9b3f6d7e 100644
--- a/pkg/validator/controllers/interface.go
+++ b/pkg/validator/controllers/interface.go
@@ -1,8 +1,6 @@
package controllers
import (
- "fmt"
-
"github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/kube"
kubeAPICoreV1 "k8s.io/api/core/v1"
@@ -13,7 +11,6 @@ import (
type Interface interface {
GetName() string
GetNamespace() string
- GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec
GetPodSpec() *kubeAPICoreV1.PodSpec
GetKind() config.SupportedController
GetObjectMeta() kubeAPIMetaV1.ObjectMeta
@@ -35,41 +32,11 @@ func (g GenericController) GetNamespace() string {
return g.Namespace
}
-// LoadControllersByKind loads a list of controllers from the kubeResources by detecting their type
-func LoadControllersByKind(controllerKind config.SupportedController, kubeResources *kube.ResourceProvider) ([]Interface, error) {
+// LoadControllers loads a list of controllers from the kubeResources Pods
+func LoadControllers(kubeResources *kube.ResourceProvider) []Interface {
interfaces := []Interface{}
- switch controllerKind {
- case config.NakedPods:
- for _, pod := range kubeResources.Pods {
- interfaces = append(interfaces, NewNakedPodController(pod))
- }
- case config.Deployments:
- for _, deploy := range kubeResources.Deployments {
- interfaces = append(interfaces, NewDeploymentController(deploy))
- }
- case config.StatefulSets:
- for _, statefulSet := range kubeResources.StatefulSets {
- interfaces = append(interfaces, NewStatefulSetController(statefulSet))
- }
- case config.DaemonSets:
- for _, daemonSet := range kubeResources.DaemonSets {
- interfaces = append(interfaces, NewDaemonSetController(daemonSet))
- }
- case config.Jobs:
- for _, job := range kubeResources.Jobs {
- interfaces = append(interfaces, NewJobController(job))
- }
- case config.CronJobs:
- for _, cronJob := range kubeResources.CronJobs {
- interfaces = append(interfaces, NewCronJobController(cronJob))
- }
- case config.ReplicationControllers:
- for _, replicationController := range kubeResources.ReplicationControllers {
- interfaces = append(interfaces, NewReplicationControllerController(replicationController))
- }
+ for _, pod := range kubeResources.Pods {
+ interfaces = append(interfaces, NewNakedPodController(pod))
}
- if len(interfaces) > 0 {
- return interfaces, nil
- }
- return nil, fmt.Errorf("Controller type (%s) does not have a generator", controllerKind)
+ return interfaces
}
diff --git a/pkg/validator/controllers/job.go b/pkg/validator/controllers/job.go
index 3efe181c..699f8588 100644
--- a/pkg/validator/controllers/job.go
+++ b/pkg/validator/controllers/job.go
@@ -13,11 +13,6 @@ type JobController struct {
K8SResource kubeAPIBatchV1.Job
}
-// GetPodTemplate returns the original template spec
-func (j JobController) GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec {
- return &j.K8SResource.Spec.Template
-}
-
// GetPodSpec returns the original kubernetes template pod spec
func (j JobController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &j.K8SResource.Spec.Template.Spec
diff --git a/pkg/validator/controllers/naked-pod.go b/pkg/validator/controllers/naked-pod.go
index c5ab8e66..6086f15a 100644
--- a/pkg/validator/controllers/naked-pod.go
+++ b/pkg/validator/controllers/naked-pod.go
@@ -12,11 +12,6 @@ type NakedPodController struct {
K8SResource kubeAPICoreV1.Pod
}
-// GetPodTemplate returns the original template spec
-func (n NakedPodController) GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec {
- return nil
-}
-
// GetPodSpec returns the original kubernetes template pod spec
func (n NakedPodController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &n.K8SResource.Spec
diff --git a/pkg/validator/controllers/replicationcontroller.go b/pkg/validator/controllers/replicationcontroller.go
index cb510f88..43cf110e 100644
--- a/pkg/validator/controllers/replicationcontroller.go
+++ b/pkg/validator/controllers/replicationcontroller.go
@@ -15,11 +15,6 @@ type ReplicationControllerController struct {
K8SResource kubeAPICoreV1.ReplicationController
}
-// GetPodTemplate returns the original template spec
-func (r ReplicationControllerController) GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec {
- return r.K8SResource.Spec.Template
-}
-
// GetPodSpec returns the original kubernetes template pod spec
func (r ReplicationControllerController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &r.K8SResource.Spec.Template.Spec
diff --git a/pkg/validator/controllers/statefulsets.go b/pkg/validator/controllers/statefulsets.go
index 4ac1f62b..e49598f1 100644
--- a/pkg/validator/controllers/statefulsets.go
+++ b/pkg/validator/controllers/statefulsets.go
@@ -13,11 +13,6 @@ type StatefulSetController struct {
K8SResource kubeAPIAppsV1.StatefulSet
}
-// GetPodTemplate returns the kubernetes template spec
-func (s StatefulSetController) GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec {
- return &s.K8SResource.Spec.Template
-}
-
// GetPodSpec returns the podspec from the original kubernetes resource
func (s StatefulSetController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &s.K8SResource.Spec.Template.Spec
diff --git a/pkg/validator/fullaudit.go b/pkg/validator/fullaudit.go
index 06eb6e93..7c3e8ed4 100644
--- a/pkg/validator/fullaudit.go
+++ b/pkg/validator/fullaudit.go
@@ -34,16 +34,11 @@ func RunAudit(config conf.Configuration, kubeResources *kube.ResourceProvider) (
SourceName: kubeResources.SourceName,
DisplayName: displayName,
ClusterInfo: ClusterInfo{
- Version: kubeResources.ServerVersion,
- Nodes: len(kubeResources.Nodes),
- Pods: len(kubeResources.Pods),
- Namespaces: len(kubeResources.Namespaces),
- Deployments: len(kubeResources.Deployments),
- StatefulSets: len(kubeResources.StatefulSets),
- DaemonSets: len(kubeResources.DaemonSets),
- Jobs: len(kubeResources.Jobs),
- CronJobs: len(kubeResources.CronJobs),
- ReplicationControllers: len(kubeResources.ReplicationControllers),
+ Version: kubeResources.ServerVersion,
+ Nodes: len(kubeResources.Nodes),
+ Pods: len(kubeResources.Pods),
+ Namespaces: len(kubeResources.Namespaces),
+ Controllers: len(results),
},
Results: results,
}
diff --git a/pkg/validator/fullaudit_test.go b/pkg/validator/fullaudit_test.go
index c5cdd7f8..3b3750d4 100644
--- a/pkg/validator/fullaudit_test.go
+++ b/pkg/validator/fullaudit_test.go
@@ -13,7 +13,7 @@ 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")
+ resources, err := kube.CreateResourceProviderFromAPI(k8s, "test", nil)
assert.Equal(t, err, nil, "error should be nil")
c := conf.Configuration{
@@ -33,8 +33,8 @@ func TestGetTemplateData(t *testing.T) {
sum := CountSummary{
Successes: uint(0),
- Warnings: uint(9),
- Errors: uint(9),
+ Warnings: uint(1),
+ Errors: uint(1),
}
actualAudit, err := RunAudit(c, resources)
@@ -48,17 +48,7 @@ func TestGetTemplateData(t *testing.T) {
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},
+ {kind: "NakedPod", results: 2},
}
assert.Equal(t, len(expected), len(actualAudit.Results))
diff --git a/pkg/validator/output.go b/pkg/validator/output.go
index 9df68e38..845daaeb 100644
--- a/pkg/validator/output.go
+++ b/pkg/validator/output.go
@@ -15,8 +15,9 @@
package validator
import (
- "github.com/fairwindsops/polaris/pkg/config"
"time"
+
+ "github.com/fairwindsops/polaris/pkg/config"
)
const (
@@ -37,16 +38,11 @@ type AuditData struct {
// ClusterInfo contains Polaris results as well as some high-level stats
type ClusterInfo struct {
- Version string
- Nodes int
- Pods int
- Namespaces int
- Deployments int
- StatefulSets int
- DaemonSets int
- Jobs int
- CronJobs int
- ReplicationControllers int
+ Version string
+ Nodes int
+ Pods int
+ Namespaces int
+ Controllers int
}
// ResultMessage is the result of a given check
diff --git a/pkg/validator/pod.go b/pkg/validator/pod.go
index 420ef39f..32d9e29e 100644
--- a/pkg/validator/pod.go
+++ b/pkg/validator/pod.go
@@ -25,7 +25,6 @@ func ValidatePod(conf *config.Configuration, controller controllers.Interface) (
if err != nil {
return PodResult{}, err
}
-
pRes := PodResult{
Results: podResults,
ContainerResults: []ContainerResult{},
@@ -35,6 +34,5 @@ func ValidatePod(conf *config.Configuration, controller controllers.Interface) (
if err != nil {
return pRes, err
}
-
return pRes, nil
}
diff --git a/test/fixtures.go b/test/fixtures.go
index 303b0613..272ab38c 100644
--- a/test/fixtures.go
+++ b/test/fixtures.go
@@ -32,6 +32,13 @@ func MockPod() corev1.PodTemplateSpec {
return p
}
+// MockNakedPod created a pod object.
+func MockNakedPod() corev1.Pod {
+ return corev1.Pod{
+ Spec: MockPod().Spec,
+ }
+}
+
// MockDeploy creates a Deployment object.
func MockDeploy() appsv1.Deployment {
p := MockPod()
@@ -132,6 +139,11 @@ func SetupAddControllers(k kubernetes.Interface, namespace string) kubernetes.In
panic(err)
}
+ p1 := MockNakedPod()
+ if _, err := k.CoreV1().Pods(namespace).Create(&p1); err != nil {
+ panic(err)
+ }
+
return k
}