// TODO: Consider using a mocking library instead or fully fleshing this out into a fake impl and putting it in some // generally available location func (f *Factory) ValidateBytes(data []byte) error { var obj interface{} out, err := k8syaml.ToJSON(data) if err != nil { return err } data = out if err := json.Unmarshal(data, &obj); err != nil { return err } fields, ok := obj.(map[string]interface{}) if !ok { return fmt.Errorf("error in unmarshaling data %s", string(data)) } // Note: This only supports the 2 api versions we expect from the test it is currently supporting. groupVersion := fields["apiVersion"] switch groupVersion { case "v1": return f.defaultSchema.ValidateBytes(data) case "extensions/v1beta1": return f.extensionsSchema.ValidateBytes(data) default: return fmt.Errorf("Unsupported API version %s", groupVersion) } }
// NewDelta accepts two JSON or YAML documents and calculates the difference // between them. It returns a Delta object which can be used to resolve // conflicts against a third version with a common parent, or an error // if either document is in error. func NewDelta(from, to []byte) (*Delta, error) { d := &Delta{} before, err := yaml.ToJSON(from) if err != nil { return nil, err } after, err := yaml.ToJSON(to) if err != nil { return nil, err } diff, err := jsonpatch.CreateMergePatch(before, after) if err != nil { return nil, err } glog.V(6).Infof("Patch created from:\n%s\n%s\n%s", string(before), string(after), string(diff)) d.original = before d.edit = diff return d, nil }
// Apply attempts to apply the changes described by Delta onto latest, // returning an error if the changes cannot be applied cleanly. // IsConflicting will be true if the changes overlap, otherwise a // generic error will be returned. func (d *Delta) Apply(latest []byte) ([]byte, error) { base, err := yaml.ToJSON(latest) if err != nil { return nil, err } changes, err := jsonpatch.CreateMergePatch(d.original, base) if err != nil { return nil, err } diff1 := make(map[string]interface{}) if err := json.Unmarshal(d.edit, &diff1); err != nil { return nil, err } diff2 := make(map[string]interface{}) if err := json.Unmarshal(changes, &diff2); err != nil { return nil, err } for _, fn := range d.preconditions { hold1, _ := fn(diff1) hold2, _ := fn(diff2) if !hold1 || !hold2 { return nil, ErrPreconditionFailed } } glog.V(6).Infof("Testing for conflict between:\n%s\n%s", string(d.edit), string(changes)) hasConflicts, err := strategicpatch.HasConflicts(diff1, diff2) if err != nil { return nil, err } if hasConflicts { return nil, ErrConflict } return jsonpatch.MergePatch(base, d.edit) }