@ -609,27 +609,29 @@ func deleteResource(info *resource.Info, policy metav1.DeletionPropagation) erro
return err
return err
}
}
func createPatch ( target * resource . Info , current runtime . Object ) ( [ ] byte , types . PatchType , error ) {
func createPatch ( target * resource . Info , current runtime . Object ) ( [ ] byte , types . PatchType , bool , error ) {
isCRDOrUnstructured := false
oldData , err := json . Marshal ( current )
oldData , err := json . Marshal ( current )
if err != nil {
if err != nil {
return nil , types . StrategicMergePatchType , errors. Wrap ( err , "serializing current configuration" )
return nil , types . StrategicMergePatchType , isCRDOrUnstructured, errors. Wrap ( err , "serializing current configuration" )
}
}
newData , err := json . Marshal ( target . Object )
newData , err := json . Marshal ( target . Object )
if err != nil {
if err != nil {
return nil , types . StrategicMergePatchType , errors. Wrap ( err , "serializing target configuration" )
return nil , types . StrategicMergePatchType , isCRDOrUnstructured, errors. Wrap ( err , "serializing target configuration" )
}
}
// Fetch the current object for the three way merge
// Fetch the current object for the three way merge
helper := resource . NewHelper ( target . Client , target . Mapping ) . WithFieldManager ( getManagedFieldsManager ( ) )
helper := resource . NewHelper ( target . Client , target . Mapping ) . WithFieldManager ( getManagedFieldsManager ( ) )
currentObj , err := helper . Get ( target . Namespace , target . Name )
currentObj , err := helper . Get ( target . Namespace , target . Name )
if err != nil && ! apierrors . IsNotFound ( err ) {
if err != nil && ! apierrors . IsNotFound ( err ) {
return nil , types . StrategicMergePatchType , errors. Wrapf ( err , "unable to get data for current object %s/%s" , target . Namespace , target . Name )
return nil , types . StrategicMergePatchType , isCRDOrUnstructured, errors. Wrapf ( err , "unable to get data for current object %s/%s" , target . Namespace , target . Name )
}
}
// Even if currentObj is nil (because it was not found), it will marshal just fine
// Even if currentObj is nil (because it was not found), it will marshal just fine
currentData , err := json . Marshal ( currentObj )
currentData , err := json . Marshal ( currentObj )
if err != nil {
if err != nil {
return nil , types . StrategicMergePatchType , errors. Wrap ( err , "serializing live configuration" )
return nil , types . StrategicMergePatchType , isCRDOrUnstructured, errors. Wrap ( err , "serializing live configuration" )
}
}
// Get a versioned object
// Get a versioned object
@ -647,16 +649,17 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P
if isUnstructured || isCRD {
if isUnstructured || isCRD {
// fall back to generic JSON merge patch
// fall back to generic JSON merge patch
patch , err := jsonpatch . CreateMergePatch ( oldData , newData )
patch , err := jsonpatch . CreateMergePatch ( oldData , newData )
return patch , types . MergePatchType , err
isCRDOrUnstructured = true
return patch , types . MergePatchType , isCRDOrUnstructured , err
}
}
patchMeta , err := strategicpatch . NewPatchMetaFromStruct ( versionedObject )
patchMeta , err := strategicpatch . NewPatchMetaFromStruct ( versionedObject )
if err != nil {
if err != nil {
return nil , types . StrategicMergePatchType , errors. Wrap ( err , "unable to create patch metadata from object" )
return nil , types . StrategicMergePatchType , isCRDOrUnstructured, errors. Wrap ( err , "unable to create patch metadata from object" )
}
}
patch , err := strategicpatch . CreateThreeWayMergePatch ( oldData , newData , currentData , patchMeta , true )
patch , err := strategicpatch . CreateThreeWayMergePatch ( oldData , newData , currentData , patchMeta , true )
return patch , types . StrategicMergePatchType , err
return patch , types . StrategicMergePatchType , isCRDOrUnstructured, err
}
}
func updateResource ( c * Client , target * resource . Info , currentObj runtime . Object , force bool ) error {
func updateResource ( c * Client , target * resource . Info , currentObj runtime . Object , force bool ) error {
@ -675,7 +678,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
}
}
c . Log ( "Replaced %q with kind %s for kind %s" , target . Name , currentObj . GetObjectKind ( ) . GroupVersionKind ( ) . Kind , kind )
c . Log ( "Replaced %q with kind %s for kind %s" , target . Name , currentObj . GetObjectKind ( ) . GroupVersionKind ( ) . Kind , kind )
} else {
} else {
patch , patchType , err := createPatch ( target , currentObj )
patch , patchType , isCRDOrUnstructured, err := createPatch ( target , currentObj )
if err != nil {
if err != nil {
return errors . Wrap ( err , "failed to create patch" )
return errors . Wrap ( err , "failed to create patch" )
}
}
@ -690,8 +693,14 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
return nil
return nil
}
}
// send patch to server
// send patch to server
c . Log ( "Patch %s %q in namespace %s" , kind , target . Name , target . Namespace )
if isCRDOrUnstructured {
obj , err = helper . Patch ( target . Namespace , target . Name , patchType , patch , nil )
// CRDs and Unstructured resources do not support strategic merge patch, so just replace it
c . Log ( "Custom or Unstructured Resouce Replace %s %q in namespace %s " , kind , target . Name , target . Namespace )
obj , err = helper . Replace ( target . Namespace , target . Name , true , target . Object )
} else {
c . Log ( "Patch %s %q in namespace %s" , kind , target . Name , target . Namespace )
obj , err = helper . Patch ( target . Namespace , target . Name , patchType , patch , nil )
}
if err != nil {
if err != nil {
return errors . Wrapf ( err , "cannot patch %q with kind %s" , target . Name , kind )
return errors . Wrapf ( err , "cannot patch %q with kind %s" , target . Name , kind )
}
}