in pkg/controller/direct/compute/forwardingrule/forwardingrule_controller.go [302:416]
func (a *forwardingRuleAdapter) Update(ctx context.Context, updateOp *directbase.UpdateOperation) error {
u := updateOp.GetUnstructured()
var err error
if a.id.forwardingRule == "" {
return fmt.Errorf("resourceID is empty")
}
err = resolveDependencies(ctx, a.reader, a.desired)
if err != nil {
return err
}
log := klog.FromContext(ctx).WithName(ctrlName)
log.V(2).Info("updating ComputeForwardingRule", "name", a.id.forwardingRule)
mapCtx := &direct.MapContext{}
desired := a.desired.DeepCopy()
forwardingRule := ComputeForwardingRuleSpec_ToProto(mapCtx, &desired.Spec)
if mapCtx.Err() != nil {
return mapCtx.Err()
}
forwardingRule.Name = direct.LazyPtr(a.id.forwardingRule)
forwardingRule.Labels = desired.Labels
op := &gcp.Operation{}
updated := &computepb.ForwardingRule{}
if !reflect.DeepEqual(forwardingRule.AllowGlobalAccess, a.actual.AllowGlobalAccess) {
// To match the request body in TF-controller log
// https://github.com/hashicorp/terraform-provider-google/blob/main/google/services/compute/resource_compute_forwarding_rule.go#L1151
reqBody := &computepb.ForwardingRule{AllowGlobalAccess: forwardingRule.AllowGlobalAccess}
if a.id.location == "global" {
// TF does not support allowGlobalAccess field for global forwarding rule
// Underlying API as well, error message: `Field allow-global-access is only supported for regional INTERNAL
// forwarding rules with backend service/target instance or regional INTERNAL_MANAGED forwarding rules.`
forwardingRule.AllowGlobalAccess = nil
} else {
patchReq := &computepb.PatchForwardingRuleRequest{
ForwardingRule: a.id.forwardingRule,
ForwardingRuleResource: reqBody,
Project: a.id.project,
Region: a.id.location,
}
op, err = a.forwardingRulesClient.Patch(ctx, patchReq)
}
if err != nil {
return fmt.Errorf("updating ComputeForwardingRule %s: %w", a.fullyQualifiedName(), err)
}
err = op.Wait(ctx)
if err != nil {
return fmt.Errorf("waiting ComputeForwardingRule %s update failed: %w", a.fullyQualifiedName(), err)
}
log.V(2).Info("successfully updated ComputeForwardingRule", "name", a.fullyQualifiedName())
}
// Use setTarget and setLabels to update target and labels fields.
if !reflect.DeepEqual(forwardingRule.Labels, a.actual.Labels) {
op, err := a.setLabels(ctx, a.actual.LabelFingerprint, forwardingRule.Labels)
if err != nil {
return fmt.Errorf("updating ComputeForwardingRule labels %s: %w", a.fullyQualifiedName(), err)
}
if !op.Done() {
err = op.Wait(ctx)
if err != nil {
return fmt.Errorf("waiting ComputeForwardingRule %s update labels failed: %w", a.fullyQualifiedName(), err)
}
}
log.V(2).Info("successfully updated ComputeForwardingRule labels", "name", a.fullyQualifiedName())
}
// setTarget request is sent when there are updates to target.
// IsSelfLinkEqual is a special handling to avoid reconciliation discrepancies caused by resources and
// their dependencies being managed by different controllers.
// This can be removed once all Compute resources are migrated to direct controller.
if !compute.IsSelfLinkEqual(forwardingRule.Target, a.actual.Target) {
if a.id.location == "global" {
setTargetReq := &computepb.SetTargetGlobalForwardingRuleRequest{
ForwardingRule: a.id.forwardingRule,
TargetReferenceResource: &computepb.TargetReference{Target: forwardingRule.Target},
Project: a.id.project,
}
op, err = a.globalForwardingRulesClient.SetTarget(ctx, setTargetReq)
} else {
setTargetReq := &computepb.SetTargetForwardingRuleRequest{
ForwardingRule: a.id.forwardingRule,
TargetReferenceResource: &computepb.TargetReference{Target: forwardingRule.Target},
Project: a.id.project,
Region: a.id.location,
}
op, err = a.forwardingRulesClient.SetTarget(ctx, setTargetReq)
}
if err != nil {
return fmt.Errorf("updating ComputeForwardingRule target %s: %w", a.fullyQualifiedName(), err)
}
if !op.Done() {
err = op.Wait(ctx)
if err != nil {
return fmt.Errorf("waiting ComputeForwardingRule %s update target failed: %w", a.fullyQualifiedName(), err)
}
}
log.V(2).Info("successfully updated ComputeForwardingRule target", "name", a.fullyQualifiedName())
}
// Get the updated resource
updated, err = a.get(ctx)
if err != nil {
return fmt.Errorf("getting ComputeForwardingRule %q: %w", a.id.forwardingRule, err)
}
status := &krm.ComputeForwardingRuleStatus{
LabelFingerprint: updated.LabelFingerprint,
CreationTimestamp: updated.CreationTimestamp,
SelfLink: updated.SelfLink,
}
return setStatus(u, status)
}