diff --git a/util/diff/diff.go b/util/diff/diff.go index 5d28ee375d5cc..d5c17ca81dc41 100644 --- a/util/diff/diff.go +++ b/util/diff/diff.go @@ -26,7 +26,7 @@ func Diff(left, right *unstructured.Unstructured) *DiffResult { leftObj = left.Object } if right != nil { - rightObj = removeMapFields(leftObj, right.Object) + rightObj = RemoveMapFields(leftObj, right.Object) } gjDiff := gojsondiff.New().CompareObjects(leftObj, rightObj) dr := DiffResult{ @@ -75,7 +75,7 @@ func (d *DiffResult) ASCIIFormat(left *unstructured.Unstructured, formatOpts for func removeFields(config, live interface{}) interface{} { switch c := config.(type) { case map[string]interface{}: - return removeMapFields(c, live.(map[string]interface{})) + return RemoveMapFields(c, live.(map[string]interface{})) case []interface{}: return removeListFields(c, live.([]interface{})) default: @@ -83,7 +83,7 @@ func removeFields(config, live interface{}) interface{} { } } -func removeMapFields(config, live map[string]interface{}) map[string]interface{} { +func RemoveMapFields(config, live map[string]interface{}) map[string]interface{} { result := map[string]interface{}{} for k, v1 := range config { v2, ok := live[k] diff --git a/util/ksonnet/ksonnet.go b/util/ksonnet/ksonnet.go index 36cc7ae14fe1f..fbeae9e8de7dc 100644 --- a/util/ksonnet/ksonnet.go +++ b/util/ksonnet/ksonnet.go @@ -8,13 +8,20 @@ import ( "strconv" "strings" + "encoding/json" + "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1" "github.com/argoproj/argo-cd/util/cli" + "github.com/argoproj/argo-cd/util/diff" "github.com/ghodss/yaml" "github.com/ksonnet/ksonnet/pkg/app" "github.com/ksonnet/ksonnet/pkg/component" log "github.com/sirupsen/logrus" "github.com/spf13/afero" + "k8s.io/api/apps/v1beta1" + "k8s.io/api/apps/v1beta2" + corev1 "k8s.io/api/core/v1" + v1ExtBeta1 "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -132,12 +139,58 @@ func (k *ksonnetApp) Show(environment string) ([]*unstructured.Unstructured, err if err != nil { return nil, fmt.Errorf("Failed to unmarshal manifest from `ks show`") } + err = remarshal(&obj) + if err != nil { + return nil, err + } objs = append(objs, &obj) } // TODO(jessesuen): we need to sort objects based on their dependency order of creation return objs, nil } +// remarshal checks resource kind and version and re-marshal using corresponding struct custom marshaller. This ensures that expected resource state is formatter same as actual +// resource state in kubernetes and allows to find differences between actual and target states more accurate. +func remarshal(obj *unstructured.Unstructured) error { + var newObj interface{} + switch obj.GetAPIVersion() + ":" + obj.GetKind() { + case "apps/v1beta1:Deployment": + newObj = &v1beta1.Deployment{} + case "apps/v1beta2:Deployment": + newObj = &v1beta2.Deployment{} + case "extensions/v1beta1": + newObj = &v1ExtBeta1.Deployment{} + case "apps/v1beta1:StatefulSet": + newObj = &v1beta1.StatefulSet{} + case "apps/v1beta2:StatefulSet": + newObj = &v1beta2.StatefulSet{} + case "v1:Service": + newObj = &corev1.Service{} + } + if newObj != nil { + oldObj := obj.Object + data, err := json.Marshal(obj) + if err != nil { + return err + } + err = json.Unmarshal(data, newObj) + if err != nil { + return err + } + data, err = json.Marshal(newObj) + if err != nil { + return err + } + err = json.Unmarshal(data, obj) + if err != nil { + return err + } + // remove all default values specified by custom formatter + obj.Object = diff.RemoveMapFields(oldObj, obj.Object) + } + return nil +} + // ListEnvParams returns list of environment parameters func (k *ksonnetApp) ListEnvParams(environment string) ([]*v1alpha1.ComponentParameter, error) { mod, err := component.DefaultManager.Module(k.app, "")