Skip to content

Commit

Permalink
add backend service reference
Browse files Browse the repository at this point in the history
  • Loading branch information
gemmahou committed Dec 12, 2024
1 parent bc85425 commit dcb2ad6
Show file tree
Hide file tree
Showing 17 changed files with 178 additions and 197 deletions.
2 changes: 1 addition & 1 deletion apis/compute/v1beta1/forwardingrule_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ type ComputeForwardingRuleSpec struct {
/* A ComputeBackendService to receive the matched traffic. This is
used only for internal load balancing. */
// +optional
BackendServiceRef *refs.ComputeBackendServiceRef `json:"backendServiceRef,omitempty"`
BackendServiceRef *ComputeBackendServiceRef `json:"backendServiceRef,omitempty"`

/* Immutable. An optional description of this resource. Provide this property when
you create the resource. */
Expand Down
3 changes: 1 addition & 2 deletions apis/compute/v1beta1/targettcpproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package v1beta1

import (
refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand All @@ -34,7 +33,7 @@ var (
type ComputeTargetTCPProxySpec struct {
// A reference to the ComputeBackendService resource.
// +required
BackendServiceRef *refs.ComputeBackendServiceRef `json:"backendServiceRef"`
BackendServiceRef *ComputeBackendServiceRef `json:"backendServiceRef"`

// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Description is immutable"
// Immutable. An optional description of this resource.
Expand Down
34 changes: 32 additions & 2 deletions apis/compute/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 0 additions & 9 deletions apis/refs/v1beta1/computerefs.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,6 @@ type ComputeAddressRef struct {
Namespace string `json:"namespace,omitempty"`
}

type ComputeBackendServiceRef struct {
/* The ComputeBackendService selflink in the form "projects/{{project}}/global/backendServices/{{name}}" or "projects/{{project}}/regions/{{region}}/backendServices/{{name}}" when not managed by Config Connector. */
External string `json:"external,omitempty"`
/* The `name` field of a `ComputeBackendService` resource. */
Name string `json:"name,omitempty"`
/* The `namespace` field of a `ComputeBackendService` resource. */
Namespace string `json:"namespace,omitempty"`
}

type ComputeServiceAttachmentRef struct {
/* The ComputeServiceAttachment selflink in the form "projects/{{project}}/regions/{{region}}/serviceAttachments/{{name}}" when not managed by Config Connector. */
External string `json:"external,omitempty"`
Expand Down
19 changes: 19 additions & 0 deletions apis/refs/v1beta1/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@
package v1beta1

import (
"context"
"fmt"

"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/client"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

Expand All @@ -41,3 +47,16 @@ func GetLocation(u *unstructured.Unstructured) (string, error) {
}
return location, nil
}

func ResolveResourceName(ctx context.Context, reader client.Reader, key client.ObjectKey, gvk schema.GroupVersionKind) (*unstructured.Unstructured, error) {
resource := &unstructured.Unstructured{}
resource.SetGroupVersionKind(gvk)
if err := reader.Get(ctx, key, resource); err != nil {
if apierrors.IsNotFound(err) {
return nil, k8s.NewReferenceNotFoundError(resource.GroupVersionKind(), key)
}
return nil, fmt.Errorf("error reading referenced %v %v: %w", gvk.Kind, key, err)
}

return resource, nil
}
9 changes: 9 additions & 0 deletions apis/refs/v1beta1/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

type ReferenceContext struct {
// Whether a referenced resource is only managed by direct controller
IsDirectOnly bool

// the referenced resource's field that will be extracted and set as the value of referenced field
// If IsDirectOnly is false, TargetField is required
TargetField string
}

type ExternalNormalizer interface {
// NormalizedExternal expects the implemented struct has a "External" field, and this function
// assigns a value to the "External" field if it is empty.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,15 @@ spec:
- external
properties:
external:
description: The ComputeBackendService selflink in the form "projects/{{project}}/global/backendServices/{{name}}"
or "projects/{{project}}/regions/{{region}}/backendServices/{{name}}"
when not managed by Config Connector.
description: The value of an externally managed ComputeBackendService
resource. Should be in the format "projects/{{project}}/global/backendServices/{{backendService}}"
or "projects/{{project}}/regions/{{region}}/backendServices/{{backendService}}".
type: string
name:
description: The `name` field of a `ComputeBackendService` resource.
description: The name of a ComputeBackendService resource.
type: string
namespace:
description: The `namespace` field of a `ComputeBackendService`
resource.
description: The namespace of a ComputeBackendService resource.
type: string
type: object
description:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,15 @@ spec:
- external
properties:
external:
description: The ComputeBackendService selflink in the form "projects/{{project}}/global/backendServices/{{name}}"
or "projects/{{project}}/regions/{{region}}/backendServices/{{name}}"
when not managed by Config Connector.
description: The value of an externally managed ComputeBackendService
resource. Should be in the format "projects/{{project}}/global/backendServices/{{backendService}}"
or "projects/{{project}}/regions/{{region}}/backendServices/{{backendService}}".
type: string
name:
description: The `name` field of a `ComputeBackendService` resource.
description: The name of a ComputeBackendService resource.
type: string
namespace:
description: The `namespace` field of a `ComputeBackendService`
resource.
description: The namespace of a ComputeBackendService resource.
type: string
type: object
description:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
gcp "cloud.google.com/go/compute/apiv1"
computepb "cloud.google.com/go/compute/apiv1/computepb"
krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/compute/v1beta1"
refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/config"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase"
Expand Down Expand Up @@ -539,3 +540,39 @@ func setStatus(u *unstructured.Unstructured, typedStatus any) error {

return nil
}

// This function get the normalized external values and convert it to the API required format
func resolveBackendService(ctx context.Context, reader client.Reader, obj *krm.ComputeForwardingRule) error {
// API required format: selfLink
referenceContext := refsv1beta1.ReferenceContext{IsDirectOnly: false, TargetField: "status.selfLink"}
computeBasePath := "https://www.googleapis.com/compute/v1/"
ref := obj.Spec.BackendServiceRef
if ref != nil {
// Get normalized external
_, err := ref.NormalizedExternal(ctx, reader, obj.GetNamespace())
if err != nil {
return fmt.Errorf("failed to get BackendServiceRef: %w", err)
}
// Convert normalized external to API required format
v := ref.External
// If object is DirectOnly, it is created by direct controller.
if referenceContext.IsDirectOnly {
// add the compute prefix in front
obj.Spec.BackendServiceRef.External = computeBasePath + v
return nil
}
// If object not DirectOnly, it can be created by either direct controller or legacy controller, depends on user's settings.
_, _, err = krm.ParseComputeBackendServiceExternal(v)
// Value follows KCC external format, likely it's created by direct controller
if err == nil {
// add the compute prefix in front
obj.Spec.BackendServiceRef.External = computeBasePath + v
return nil
}
// For backward compatibility, we also accept values that does not match the KCC external format.(likely it's created by legacy controller)
// Return the value as is and let the API handle it
obj.Spec.BackendServiceRef.External = v
return nil
}
return nil
}
6 changes: 3 additions & 3 deletions pkg/controller/direct/compute/forwardingrule/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,16 @@ func ComputeForwardingRuleSpec_IpAddress_FromProto(mapCtx *direct.MapContext, in
return out
}

func ComputeForwardingRuleSpec_BackendSeriviceRef_FromProto(mapCtx *direct.MapContext, in string) *refs.ComputeBackendServiceRef {
func ComputeForwardingRuleSpec_BackendSeriviceRef_FromProto(mapCtx *direct.MapContext, in string) *krm.ComputeBackendServiceRef {
if in == "" {
return nil
}
return &refs.ComputeBackendServiceRef{
return &krm.ComputeBackendServiceRef{
External: in,
}
}

func ComputeForwardingRuleSpec_BackendSeriviceRef_ToProto(mapCtx *direct.MapContext, in *refs.ComputeBackendServiceRef) *string {
func ComputeForwardingRuleSpec_BackendSeriviceRef_ToProto(mapCtx *direct.MapContext, in *krm.ComputeBackendServiceRef) *string {
if in == nil {
return nil
}
Expand Down
52 changes: 2 additions & 50 deletions pkg/controller/direct/compute/forwardingrule/refs.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,49 +178,6 @@ func ResolveComputeAddress(ctx context.Context, reader client.Reader, src client
External: address}, nil
}

func ResolveComputeBackendService(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeBackendServiceRef) (*refs.ComputeBackendServiceRef, error) {
if ref == nil {
return nil, nil
}

if ref.External != "" {
if ref.Name != "" {
return nil, fmt.Errorf("cannot specify both name and external on reference")
}
return ref, nil
}

if ref.Name == "" {
return nil, fmt.Errorf("must specify either name or external on reference")
}

key := types.NamespacedName{
Namespace: ref.Namespace,
Name: ref.Name,
}
if key.Namespace == "" {
key.Namespace = src.GetNamespace()
}

computeBackendService, err := resolveResourceName(ctx, reader, key, schema.GroupVersionKind{
Group: "compute.cnrm.cloud.google.com",
Version: "v1beta1",
Kind: "ComputeBackendService",
})
if err != nil {
return nil, err
}

// targetField: self_link
// See compute servicemappings for details
selfLink, _, err := unstructured.NestedString(computeBackendService.Object, "status", "selfLink")
if err != nil || selfLink == "" {
return nil, fmt.Errorf("cannot get selfLink for referenced %s %v (status.selfLink is empty)", computeBackendService.GetKind(), computeBackendService.GetNamespace())
}
return &refs.ComputeBackendServiceRef{
External: selfLink}, nil
}

func ResolveComputeServiceAttachment(ctx context.Context, reader client.Reader, src client.Object, ref *refs.ComputeServiceAttachmentRef) (*refs.ComputeServiceAttachmentRef, error) {
if ref == nil {
return nil, nil
Expand Down Expand Up @@ -557,13 +514,8 @@ func resolveDependencies(ctx context.Context, reader client.Reader, obj *krm.Com
}

// Get backend service
if obj.Spec.BackendServiceRef != nil {
backendServiceRef, err := ResolveComputeBackendService(ctx, reader, obj, obj.Spec.BackendServiceRef)
if err != nil {
return err

}
obj.Spec.BackendServiceRef.External = backendServiceRef.External
if err := resolveBackendService(ctx, reader, obj); err != nil {
return err
}

// Get ip address, ip address is optional
Expand Down
9 changes: 4 additions & 5 deletions pkg/controller/direct/compute/targettcpproxy/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,20 @@
package targettcpproxy

import (
refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"

krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/compute/v1beta1"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct"
)

func ComputeTargetTCPProxySpec_BackendServiceRef_FromProto(mapCtx *direct.MapContext, in string) *refs.ComputeBackendServiceRef {
func ComputeTargetTCPProxySpec_BackendServiceRef_FromProto(mapCtx *direct.MapContext, in string) *krm.ComputeBackendServiceRef {
if in == "" {
return nil
}
return &refs.ComputeBackendServiceRef{
return &krm.ComputeBackendServiceRef{
External: in,
}
}

func ComputeTargetTCPProxySpec_BackendServiceRef_ToProto(mapCtx *direct.MapContext, in *refs.ComputeBackendServiceRef) *string {
func ComputeTargetTCPProxySpec_BackendServiceRef_ToProto(mapCtx *direct.MapContext, in *krm.ComputeBackendServiceRef) *string {
if in == nil {
return nil
}
Expand Down
Loading

0 comments on commit dcb2ad6

Please sign in to comment.