func()

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)
}