diff --git a/go.mod b/go.mod index 0031202a..5f52679e 100644 --- a/go.mod +++ b/go.mod @@ -6,12 +6,14 @@ require ( cloud.google.com/go v0.65.0 // indirect github.com/Azure/go-autorest/autorest v0.11.4 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.2 // indirect + github.com/fairwindsops/controller-utils v0.1.0 github.com/gobuffalo/packr/v2 v2.8.0 github.com/google/go-cmp v0.5.2 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gophercloud/gophercloud v0.12.0 // indirect github.com/gorilla/mux v1.8.0 github.com/imdario/mergo v0.3.11 // indirect + github.com/jessevdk/go-flags v1.4.0 // indirect github.com/karrick/godirwalk v1.16.1 // indirect github.com/kr/pretty v0.2.0 // indirect github.com/prometheus/common v0.13.0 // indirect @@ -30,11 +32,10 @@ require ( golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect gomodules.xyz/jsonpatch/v2 v2.1.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 - k8s.io/api v0.18.8 - k8s.io/apimachinery v0.18.8 - k8s.io/client-go v0.18.6 + k8s.io/api v0.18.9 + k8s.io/apimachinery v0.18.9 + k8s.io/client-go v0.18.9 k8s.io/klog/v2 v2.1.0 // indirect - k8s.io/utils v0.0.0-20200821003339-5e75c0163111 // indirect sigs.k8s.io/controller-runtime v0.6.3 sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index f88189c5..68512cbb 100644 --- a/go.sum +++ b/go.sum @@ -982,6 +982,8 @@ k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4= k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= k8s.io/api v0.18.8 h1:aIKUzJPb96f3fKec2lxtY7acZC9gQNDLVhfSGpxBAC4= k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY= +k8s.io/api v0.18.9 h1:7VDtivqwbvLOf8hmXSd/PDSSbpCBq49MELg84EYBYiQ= +k8s.io/api v0.18.9/go.mod h1:9u/h6sUh6FxfErv7QqetX1EB3yBMIYOBXzdcf0Gf0rc= k8s.io/apiextensions-apiserver v0.18.4 h1:Y3HGERmS8t9u12YNUFoOISqefaoGRuTc43AYCLzWmWE= k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio= k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo= @@ -990,12 +992,16 @@ k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCk k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= k8s.io/apimachinery v0.18.8 h1:jimPrycCqgx2QPearX3to1JePz7wSbVLq+7PdBTTwQ0= k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig= +k8s.io/apimachinery v0.18.9 h1:3ZABKQx3F3xPWlsGhCfUl8W+JXRRblV6Wo2A3zn0pvY= +k8s.io/apimachinery v0.18.9/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk= k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8= k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg= k8s.io/client-go v0.18.4 h1:un55V1Q/B3JO3A76eS0kUSywgGK/WR3BQ8fHQjNa6Zc= k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g= k8s.io/client-go v0.18.6 h1:I+oWqJbibLSGsZj8Xs8F0aWVXJVIoUHWaaJV3kUN/Zw= k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q= +k8s.io/client-go v0.18.9 h1:sPHX49yOtUqv1fl49TwV3f8cC0N3etSnwgFGsIsXnZc= +k8s.io/client-go v0.18.9/go.mod h1:UjkEetDmr40P9NX0Ok3Idt08FCf2I4mIHgjFsot77uY= k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk= @@ -1015,6 +1021,8 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20200821003339-5e75c0163111 h1:AChSIFe1D4vQ5XkklbH491v1ONSmnt8fnb235DsAw1U= k8s.io/utils v0.0.0-20200821003339-5e75c0163111/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20201005171033-6301aaf42dc7 h1:XQ0OMFdRDkDIu0b1zqEKSZdWUD7I4bZ4d4nqr8CLKbQ= +k8s.io/utils v0.0.0-20201005171033-6301aaf42dc7/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/kube/workload.go b/pkg/kube/workload.go index f4fe5e19..b37370ba 100644 --- a/pkg/kube/workload.go +++ b/pkg/kube/workload.go @@ -6,6 +6,8 @@ import ( "encoding/json" "fmt" + "github.com/fairwindsops/controller-utils/pkg/controller" + "github.com/fairwindsops/controller-utils/pkg/podspec" "github.com/sirupsen/logrus" "gopkg.in/yaml.v3" kubeAPICoreV1 "k8s.io/api/core/v1" @@ -48,17 +50,17 @@ func NewGenericWorkloadFromUnstructured(kind string, unst *unstructured.Unstruct if err != nil { return workload, err } - podSpecMap := GetPodSpec(m) + podSpecMap := podspec.GetPodSpec(m) b, err = json.Marshal(podSpecMap) if err != nil { return workload, err } - podSpec := kubeAPICoreV1.PodSpec{} - err = json.Unmarshal(b, &podSpec) + podSpecObject := kubeAPICoreV1.PodSpec{} + err = json.Unmarshal(b, &podSpecObject) if err != nil { return workload, err } - workload.PodSpec = podSpec + workload.PodSpec = podSpecObject return workload, nil } @@ -97,57 +99,20 @@ func newGenericWorkload(ctx context.Context, podResource kubeAPICoreV1.Pod, dyna if err != nil { return workload, err } - // If an owner exists then set the name to the workload. - // This allows us to handle CRDs creating Workloads or DeploymentConfigs in OpenShift. - owners := workload.ObjectMeta.GetOwnerReferences() - lastKey := "" - for len(owners) > 0 { - if len(owners) > 1 { - logrus.Warn("More than 1 owner found") - } - firstOwner := owners[0] - if firstOwner.Kind == "Node" { - break - } - workload.Kind = firstOwner.Kind - key := fmt.Sprintf("%s/%s/%s", firstOwner.Kind, workload.ObjectMeta.GetNamespace(), firstOwner.Name) - lastKey = key - abstractObject, ok := objectCache[key] - if !ok { - err = cacheAllObjectsOfKind(ctx, firstOwner.APIVersion, firstOwner.Kind, dynamicClient, restMapper, objectCache) - if err != nil { - logrus.Warnf("Error caching objects of Kind %s %v", firstOwner.Kind, err) - break - } - abstractObject, ok = objectCache[key] - if !ok { - logrus.Errorf("Cache missed %s again", key) - break - } - } - - objMeta, err := meta.Accessor(&abstractObject) - if err != nil { - logrus.Warnf("Error retrieving parent metadata %s of API %s and Kind %s because of error: %v ", firstOwner.Name, firstOwner.APIVersion, firstOwner.Kind, err) - return workload, err - } - workload.ObjectMeta = objMeta - owners = abstractObject.GetOwnerReferences() + objMeta, err := meta.Accessor(&podResource) + if err != nil { + return workload, err + } + controllerObject, err := controller.GetTopController(ctx, *dynamicClient, *restMapper, objMeta) + if err != nil { + return workload, err } - if lastKey != "" { - bytes, err := json.Marshal(objectCache[lastKey]) - if err != nil { - return workload, err - } - workload.OriginalObjectJSON = bytes - } else { - bytes, err := json.Marshal(podResource) - if err != nil { - return workload, err - } - workload.OriginalObjectJSON = bytes + bytes, err := json.Marshal(controllerObject) + if err != nil { + return workload, err } + workload.OriginalObjectJSON = bytes return workload, nil } @@ -181,19 +146,6 @@ func getObject(ctx context.Context, namespace, kind, version, name string, dynam return object, err } -// GetPodSpec looks inside arbitrary YAML for a PodSpec -func GetPodSpec(yaml map[string]interface{}) interface{} { - for _, child := range podSpecFields { - if childYaml, ok := yaml[child]; ok { - return GetPodSpec(childYaml.(map[string]interface{})) - } - } - if _, ok := yaml["containers"]; ok { - return yaml - } - return nil -} - // GetWorkloadFromBytes parses a GenericWorkload func GetWorkloadFromBytes(contentBytes []byte) (*GenericWorkload, error) { yamlNode := make(map[string]interface{}) @@ -206,11 +158,11 @@ func GetWorkloadFromBytes(contentBytes []byte) (*GenericWorkload, error) { finalDoc["metadata"] = yamlNode["metadata"] finalDoc["apiVersion"] = "v1" finalDoc["kind"] = "Pod" - podSpec := GetPodSpec(yamlNode) - if podSpec == nil { + podSpecObject := podspec.GetPodSpec(yamlNode) + if podSpecObject == nil { return nil, nil } - finalDoc["spec"] = podSpec + finalDoc["spec"] = podSpecObject marshaledYaml, err := yaml.Marshal(finalDoc) if err != nil { logrus.Errorf("Could not marshal yaml: %v", err) diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go index 9a11ade5..aa160eda 100644 --- a/pkg/webhook/webhook.go +++ b/pkg/webhook/webhook.go @@ -25,6 +25,7 @@ import ( "github.com/fairwindsops/polaris/pkg/kube" validator "github.com/fairwindsops/polaris/pkg/validator" + "github.com/fairwindsops/controller-utils/pkg/podspec" "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -66,7 +67,7 @@ func GetObjectFromRawRequest(raw []byte) (corev1.Pod, interface{}, error) { if err != nil { return pod, originalObject, err } - podMap := kube.GetPodSpec(decoded) + podMap := podspec.GetPodSpec(decoded) if podMap == nil { return pod, originalObject, errors.New("Object does not contain pods") }