| /* |
| Copyright 2017 The Kubernetes Authors. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| package strategy |
| |
| import ( |
| "k8s.io/kubernetes/pkg/kubectl/apply" |
| ) |
| |
| // replaceVisitor creates a patch to replace a remote field value with a local field value |
| type replaceStrategy struct { |
| strategic *delegatingStrategy |
| options Options |
| } |
| |
| func createReplaceStrategy(options Options, strategic *delegatingStrategy) replaceStrategy { |
| return replaceStrategy{ |
| strategic, |
| options, |
| } |
| } |
| |
| // MergeList returns a result by merging the recorded, local and remote values |
| // - replacing the remote value with the local value |
| func (v replaceStrategy) MergeList(e apply.ListElement) (apply.Result, error) { |
| return v.doReplace(e) |
| } |
| |
| // MergeMap returns a result by merging the recorded, local and remote values |
| // - replacing the remote value with the local value |
| func (v replaceStrategy) MergeMap(e apply.MapElement) (apply.Result, error) { |
| return v.doReplace(e) |
| } |
| |
| // MergeType returns a result by merging the recorded, local and remote values |
| // - replacing the remote value with the local value |
| func (v replaceStrategy) MergeType(e apply.TypeElement) (apply.Result, error) { |
| return v.doReplace(e) |
| } |
| |
| // MergePrimitive returns a result by merging the recorded, local and remote values |
| // - replacing the remote value with the local value |
| func (v replaceStrategy) MergePrimitive(e apply.PrimitiveElement) (apply.Result, error) { |
| return v.doReplace(e) |
| } |
| |
| // MergeEmpty |
| func (v replaceStrategy) MergeEmpty(e apply.EmptyElement) (apply.Result, error) { |
| return apply.Result{Operation: apply.SET}, nil |
| } |
| |
| // replace returns the local value if specified, otherwise it returns the remote value |
| // this works regardless of the approach |
| func (v replaceStrategy) doReplace(e apply.Element) (apply.Result, error) { |
| |
| if result, done := v.doAddOrDelete(e); done { |
| return result, nil |
| } |
| if err := v.doConflictDetect(e); err != nil { |
| return apply.Result{}, err |
| } |
| if e.HasLocal() { |
| // Specified locally, set the local value |
| return apply.Result{Operation: apply.SET, MergedResult: e.GetLocal()}, nil |
| } else if e.HasRemote() { |
| // Not specified locally, set the remote value |
| return apply.Result{Operation: apply.SET, MergedResult: e.GetRemote()}, nil |
| } else { |
| // Only specified in the recorded, drop the field. |
| return apply.Result{Operation: apply.DROP, MergedResult: e.GetRemote()}, nil |
| } |
| } |
| |
| // doAddOrDelete will check if the field should be either added or deleted. If either is true, it will |
| // true the operation and true. Otherwise it will return false. |
| func (v replaceStrategy) doAddOrDelete(e apply.Element) (apply.Result, bool) { |
| if apply.IsAdd(e) { |
| return apply.Result{Operation: apply.SET, MergedResult: e.GetLocal()}, true |
| } |
| |
| // Delete the List |
| if apply.IsDrop(e) { |
| return apply.Result{Operation: apply.DROP}, true |
| } |
| |
| return apply.Result{}, false |
| } |
| |
| // doConflictDetect returns error if element has conflict |
| func (v replaceStrategy) doConflictDetect(e apply.Element) error { |
| return v.strategic.doConflictDetect(e) |
| } |
| |
| var _ apply.Strategy = &replaceStrategy{} |