Skip to content
This repository has been archived by the owner on Aug 11, 2021. It is now read-only.

Commit

Permalink
Merge logic for create and update (it's the same when using SSA)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexsomesan committed Jul 24, 2020
1 parent 4e1a774 commit 8fe2749
Showing 1 changed file with 22 additions and 88 deletions.
110 changes: 22 additions & 88 deletions provider/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -641,38 +641,38 @@ func (s *RawProviderServer) ApplyResourceChange(ctx context.Context, req *tfplug
var rs dynamic.ResourceInterface

switch {
case applyPriorState.IsNull():
{ // Create resource
case applyPriorState.IsNull() || (!applyPlannedState.IsNull() && !applyPriorState.IsNull()):
{ // Apply resource
o := sanitizedPlannedState.GetAttr("object")

gvr, err := GVRFromCtyObject(&o)
if err != nil {
return resp, err
return resp, fmt.Errorf("failed to determine resource GVR: %s", err)
}

gvk, err := GVKFromCtyObject(&o)
if err != nil {
return resp, fmt.Errorf("failed to determine resource GVR: %s", err)
return resp, fmt.Errorf("failed to determine resource GVK: %s", err)
}

tsch, err := resourceTypeFromOpenAPI(gvk)
if err != nil {
return resp, fmt.Errorf("failed to determine resource type ID: %s", err)
}

mi, err := CtyObjectToUnstructured(&o)
pu, err := CtyObjectToUnstructured(&o)
if err != nil {
return resp, err
}

// remove null attributes - the API doesn't appreciate requests that include them
uo := unstructured.Unstructured{Object: mapRemoveNulls(mi)}
ns, err := IsResourceNamespaced(gvr)
if err != nil {
return resp, err
}
// remove null attributes - the API doesn't appreciate requests that include them
uo := unstructured.Unstructured{Object: mapRemoveNulls(pu)}
rnamespace := uo.GetNamespace()
rname := uo.GetName()

if ns {
rs = c.Resource(gvr).Namespace(rnamespace)
} else {
Expand All @@ -686,18 +686,24 @@ func (s *RawProviderServer) ApplyResourceChange(ctx context.Context, req *tfplug
// Call the Kubernetes API to create the new resource
result, err := rs.Patch(ctx, rname, types.ApplyPatchType, jd, v1.PatchOptions{FieldManager: "Terraform"})
if err != nil {
Dlog.Printf("[ApplyResourceChange][Create] Error: %s\n%s\n", spew.Sdump(err), spew.Sdump(result))
n := types.NamespacedName{Namespace: rnamespace, Name: rname}.String()
return resp, fmt.Errorf("CREATE resource %s failed: %s", n, err)
Dlog.Printf("[ApplyResourceChange][Apply] Error: %s\n%s\n", spew.Sdump(err), spew.Sdump(result))
rn := types.NamespacedName{Namespace: rnamespace, Name: rname}.String()
resp.Diagnostics = append(resp.Diagnostics,
&tfplugin5.Diagnostic{
Severity: tfplugin5.Diagnostic_ERROR,
Detail: err.Error(),
Summary: fmt.Sprintf("PATCH resource %s failed: %s", rn, err),
})
return resp, fmt.Errorf("PATCH resource %s failed: %s", rn, err)
}
Dlog.Printf("[ApplyResourceChange][Create] API response:\n%s\n", spew.Sdump(result))
Dlog.Printf("[ApplyResourceChange][Apply] API response:\n%s\n", spew.Sdump(result))

fo := FilterEphemeralFields(result.Object)
newResObject, err := UnstructuredToCty(fo, tsch)
if err != nil {
return resp, err
}
Dlog.Printf("[ApplyResourceChange][Request][CtyResponse]\n%s\n", spew.Sdump(newResObject))
Dlog.Printf("[ApplyResourceChange][Apply][CtyResponse]\n%s\n", spew.Sdump(newResObject))

newResState, err := cty.Transform(sanitizedPlannedState,
ResourceDeepUpdateObjectAttr(cty.GetAttrPath("object"), &newResObject),
Expand Down Expand Up @@ -742,89 +748,17 @@ func (s *RawProviderServer) ApplyResourceChange(ctx context.Context, req *tfplug
rs = c.Resource(gvr)
}
err = rs.Delete(ctx, rname, v1.DeleteOptions{})
if err != nil {
rn := types.NamespacedName{Namespace: rnamespace, Name: rname}.String()
return resp, fmt.Errorf("DELETE resource %s failed: %s", rn, err)
}
resp.NewState = req.PlannedState
}
case !applyPlannedState.IsNull() && !applyPriorState.IsNull():
{ // Update existing resource
o := sanitizedPlannedState.GetAttr("object")

gvr, err := GVRFromCtyObject(&o)
if err != nil {
return resp, err
}

gvk, err := GVKFromCtyObject(&o)
if err != nil {
return resp, fmt.Errorf("failed to determine resource GVR: %s", err)
}

tsch, err := resourceTypeFromOpenAPI(gvk)
if err != nil {
return resp, fmt.Errorf("failed to determine resource type ID: %s", err)
}

pu, err := CtyObjectToUnstructured(&o)
if err != nil {
return resp, err
}
ns, err := IsResourceNamespaced(gvr)
if err != nil {
return resp, err
}
uo := unstructured.Unstructured{Object: pu}
rnamespace := uo.GetNamespace()
rname := uo.GetName()

c, err := GetDynamicClient()
if err != nil {
return resp, err
}
if ns {
rs = c.Resource(gvr).Namespace(rnamespace)
} else {
rs = c.Resource(gvr)
}
jd, err := uo.MarshalJSON()
if err != nil {
return resp, err
}
// Call the Kubernetes API to apply the new resource state
result, err := rs.Patch(ctx, rname, types.ApplyPatchType, jd, v1.PatchOptions{FieldManager: "Terraform"})
if err != nil {
rn := types.NamespacedName{Namespace: rnamespace, Name: rname}.String()
resp.Diagnostics = append(resp.Diagnostics,
&tfplugin5.Diagnostic{
Severity: tfplugin5.Diagnostic_ERROR,
Detail: err.Error(),
Summary: fmt.Sprintf("PATCH resource %s failed: %s", rn, err),
Summary: fmt.Sprintf("DELETE resource %s failed: %s", rn, err),
})
return resp, fmt.Errorf("PATCH resource %s failed: %s", rn, err)
}
Dlog.Printf("[ApplyResourceChange][Update] API response:\n%s\n", spew.Sdump(result))

fo := FilterEphemeralFields(result.Object)
newResObject, err := UnstructuredToCty(fo, tsch)
if err != nil {
return resp, err
}
Dlog.Printf("[ApplyResourceChange][Update] transformed response:\n%s", spew.Sdump(newResObject))

newResState, err := cty.Transform(applyPlannedState,
ResourceDeepUpdateObjectAttr(cty.GetAttrPath("object"), &newResObject),
)
if err != nil {
return resp, err
}
Dlog.Printf("[ApplyResourceChange][Update] transformed new state:\n%s", spew.Sdump(newResState))
mp, err := MarshalResource(req.TypeName, &newResState)
if err != nil {
return resp, err
return resp, fmt.Errorf("DELETE resource %s failed: %s", rn, err)
}
resp.NewState = &tfplugin5.DynamicValue{Msgpack: mp}
resp.NewState = req.PlannedState
}
}

Expand Down

0 comments on commit 8fe2749

Please sign in to comment.