Skip to content

Commit

Permalink
[NET-7657,NET-6934] Define v2 GatewayClass + GatewayClassConfig local…
Browse files Browse the repository at this point in the history
…ly (#3559)

* Define GatewayClass's spec model locally instead of consuming proto from Consul

* Update gateway resources job to use new types, constants

* Make description optional, regenerate CRD definitions

* Remove GatewayClass columns related to syncing into Consul
  • Loading branch information
nathancoleman committed Feb 7, 2024
1 parent cbb28b6 commit e8d385b
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 144 deletions.
18 changes: 6 additions & 12 deletions charts/consul/templates/crd-gatewayclasses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ spec:
scope: Cluster
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
Expand All @@ -51,9 +43,6 @@ spec:
metadata:
type: object
spec:
description: "NOTE: this should align to the GAMMA/gateway-api version,
or at least be easily translatable. \n https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.GatewayClass
\n This is a Resource type."
properties:
controllerName:
description: ControllerName is the name of the Kubernetes controller
Expand All @@ -74,13 +63,18 @@ spec:
description: The Kubernetes Kind that the referred object is
type: string
name:
description: The name of the referred object
description: The Name of the referred object
type: string
namespace:
description: The kubernetes namespace that the referred object
is in
type: string
required:
- name
type: object
required:
- controllerName
- parametersRef
type: object
status:
properties:
Expand Down
2 changes: 2 additions & 0 deletions control-plane/api/mesh/v2beta1/gateway_class_config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const KindGatewayClassConfig = "GatewayClassConfig"

func init() {
MeshSchemeBuilder.Register(&GatewayClassConfig{}, &GatewayClassConfigList{})
}
Expand Down
128 changes: 20 additions & 108 deletions control-plane/api/mesh/v2beta1/gateway_class_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,10 @@
package v2beta1

import (
"fmt"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1"
"github.com/hashicorp/consul/proto-public/pbresource"
"google.golang.org/protobuf/testing/protocmp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/hashicorp/consul-k8s/control-plane/api/common"
inject "github.com/hashicorp/consul-k8s/control-plane/connect-inject/common"
"github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants"
)

const (
gatewayClassKubeKind = "gatewayclass"
)
const KindGatewayClass = "GatewayClass"

func init() {
MeshSchemeBuilder.Register(&GatewayClass{}, &GatewayClassList{})
Expand All @@ -30,15 +16,13 @@ func init() {
// +kubebuilder:subresource:status

// GatewayClass is the Schema for the Gateway Class API
// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type==\"Synced\")].status",description="The sync status of the resource with Consul"
// +kubebuilder:printcolumn:name="Last Synced",type="date",JSONPath=".status.lastSyncedTime",description="The last successful synced time of the resource with Consul"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource"
// +kubebuilder:resource:scope=Cluster
type GatewayClass struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec pbmesh.GatewayClass `json:"spec,omitempty"`
Spec GatewayClassSpec `json:"spec,omitempty"`
Status `json:"status,omitempty"`
}

Expand All @@ -51,101 +35,29 @@ type GatewayClassList struct {
Items []*GatewayClass `json:"items"`
}

func (in *GatewayClass) ResourceID(namespace, partition string) *pbresource.ID {
return &pbresource.ID{
Name: in.Name,
Type: pbmesh.GatewayClassType,
Tenancy: &pbresource.Tenancy{
Partition: partition,
Namespace: namespace,

// Because we are explicitly defining NS/partition, this will not default and must be explicit.
// At a future point, this will move out of the Tenancy block.
PeerName: constants.DefaultConsulPeer,
},
}
}

func (in *GatewayClass) Resource(namespace, partition string) *pbresource.Resource {
return &pbresource.Resource{
Id: in.ResourceID(namespace, partition),
Data: inject.ToProtoAny(&in.Spec),
Metadata: meshConfigMeta(),
}
}

func (in *GatewayClass) AddFinalizer(f string) {
in.ObjectMeta.Finalizers = append(in.Finalizers(), f)
}

func (in *GatewayClass) RemoveFinalizer(f string) {
var newFinalizers []string
for _, oldF := range in.Finalizers() {
if oldF != f {
newFinalizers = append(newFinalizers, oldF)
}
}
in.ObjectMeta.Finalizers = newFinalizers
}

func (in *GatewayClass) Finalizers() []string {
return in.ObjectMeta.Finalizers
}
type GatewayClassSpec struct {
// ControllerName is the name of the Kubernetes controller
// that manages Gateways of this class
ControllerName string `json:"controllerName"`

func (in *GatewayClass) MatchesConsul(candidate *pbresource.Resource, namespace, partition string) bool {
return cmp.Equal(
in.Resource(namespace, partition),
candidate,
protocmp.IgnoreFields(&pbresource.Resource{}, "status", "generation", "version"),
protocmp.IgnoreFields(&pbresource.ID{}, "uid"),
protocmp.Transform(),
cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b) }),
)
}
// ParametersRef refers to a resource responsible for configuring
// the behavior of the GatewayClass.
ParametersRef *ParametersReference `json:"parametersRef"`

func (in *GatewayClass) KubeKind() string {
return gatewayClassKubeKind
// Description of GatewayClass
Description string `json:"description,omitempty"`
}

func (in *GatewayClass) KubernetesName() string {
return in.ObjectMeta.Name
}
type ParametersReference struct {
// The Kubernetes Group that the referred object belongs to
Group string `json:"group,omitempty"`

func (in *GatewayClass) SetSyncedCondition(status corev1.ConditionStatus, reason, message string) {
in.Status.Conditions = Conditions{
{
Type: ConditionSynced,
Status: status,
LastTransitionTime: metav1.Now(),
Reason: reason,
Message: message,
},
}
}
// The Kubernetes Kind that the referred object is
Kind string `json:"kind,omitempty"`

func (in *GatewayClass) SetLastSyncedTime(time *metav1.Time) {
in.Status.LastSyncedTime = time
}
// The Name of the referred object
Name string `json:"name"`

func (in *GatewayClass) SyncedCondition() (status corev1.ConditionStatus, reason, message string) {
cond := in.Status.GetCondition(ConditionSynced)
if cond == nil {
return corev1.ConditionUnknown, "", ""
}
return cond.Status, cond.Reason, cond.Message
// The kubernetes namespace that the referred object is in
Namespace *string `json:"namespace,omitempty"`
}

func (in *GatewayClass) SyncedConditionStatus() corev1.ConditionStatus {
condition := in.Status.GetCondition(ConditionSynced)
if condition == nil {
return corev1.ConditionUnknown
}
return condition.Status
}

func (in *GatewayClass) Validate(tenancy common.ConsulTenancyConfig) error {
return nil
}

// DefaultNamespaceFields is required as part of the common.MeshConfig interface.
func (in *GatewayClass) DefaultNamespaceFields(tenancy common.ConsulTenancyConfig) {}
40 changes: 40 additions & 0 deletions control-plane/api/mesh/v2beta1/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ spec:
scope: Cluster
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
Expand All @@ -47,9 +39,6 @@ spec:
metadata:
type: object
spec:
description: "NOTE: this should align to the GAMMA/gateway-api version,
or at least be easily translatable. \n https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.GatewayClass
\n This is a Resource type."
properties:
controllerName:
description: ControllerName is the name of the Kubernetes controller
Expand All @@ -70,13 +59,18 @@ spec:
description: The Kubernetes Kind that the referred object is
type: string
name:
description: The name of the referred object
description: The Name of the referred object
type: string
namespace:
description: The kubernetes namespace that the referred object
is in
type: string
required:
- name
type: object
required:
- controllerName
- parametersRef
type: object
status:
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type GatewayClassConfigController struct {
// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=gatewayclassconfig,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=gatewayclassconfig/status,verbs=get;update;patch

func (r *GatewayClassConfigController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
func (r *GatewayClassConfigController) Reconcile(_ context.Context, _ ctrl.Request) (ctrl.Result, error) {
// GatewayClassConfig is not synced into Consul because Consul has no use for it.
// Consul is only aware of the resource for the sake of Kubernetes CRD generation.
return ctrl.Result{}, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type GatewayClassController struct {
// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=gatewayclass,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=mesh.consul.hashicorp.com,resources=gatewayclass/status,verbs=get;update;patch

func (r *GatewayClassController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
func (r *GatewayClassController) Reconcile(_ context.Context, _ ctrl.Request) (ctrl.Result, error) {
// GatewayClass is not synced into Consul because Consul has no use for it.
// Consul is only aware of the resource for the sake of Kubernetes CRD generation.
return ctrl.Result{}, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ func (r *MeshGatewayController) getGatewayClassConfigForGatewayClass(ctx context

config := &meshv2beta1.GatewayClassConfig{}
if ref := gatewayClass.Spec.ParametersRef; ref != nil {
if ref.Group != meshv2beta1.MeshGroup || ref.Kind != "GatewayClassConfig" {
if ref.Group != meshv2beta1.MeshGroup || ref.Kind != meshv2beta1.KindGatewayClassConfig {
// TODO @Gateway-Management additionally check for controller name when available
return nil, nil
}
Expand Down
11 changes: 4 additions & 7 deletions control-plane/subcommand/gateway-resources/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import (
gwv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
k8syaml "sigs.k8s.io/yaml"

meshv2beta1 "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1"

authv2beta1 "github.com/hashicorp/consul-k8s/control-plane/api/auth/v2beta1"

"github.com/hashicorp/consul-k8s/control-plane/api-gateway/common"
Expand Down Expand Up @@ -432,15 +430,14 @@ func (c *Command) createV2GatewayClassAndClassConfigs(ctx context.Context, compo
return err
}

// TODO: NET-6934 remove hardcoded values
class := &v2beta1.GatewayClass{
ObjectMeta: metav1.ObjectMeta{Name: cfg.Name, Labels: labels},
TypeMeta: metav1.TypeMeta{Kind: "GatewayClass"},
Spec: meshv2beta1.GatewayClass{
TypeMeta: metav1.TypeMeta{Kind: v2beta1.KindGatewayClass},
Spec: v2beta1.GatewayClassSpec{
ControllerName: controllerName,
ParametersRef: &meshv2beta1.ParametersReference{
ParametersRef: &v2beta1.ParametersReference{
Group: v2beta1.MeshGroup,
Kind: "GatewayClassConfig",
Kind: v2beta1.KindGatewayClassConfig,
Namespace: &cfg.Namespace,
Name: cfg.Name,
},
Expand Down
5 changes: 3 additions & 2 deletions control-plane/subcommand/gateway-resources/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"
gwv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"

meshv2beta1 "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1"

"github.com/hashicorp/consul-k8s/control-plane/api/mesh/v2beta1"
"github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1"
meshv2beta1 "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1"
)

func TestRun_flagValidation(t *testing.T) {
Expand Down Expand Up @@ -549,7 +550,7 @@ func TestRun_loadGatewayConfigs(t *testing.T) {
expectedClassConfig := v2beta1.GatewayClassConfig{
TypeMeta: metav1.TypeMeta{
APIVersion: v2beta1.MeshGroupVersion.String(),
Kind: "GatewayClassConfig",
Kind: v2beta1.KindGatewayClassConfig,
},
ObjectMeta: metav1.ObjectMeta{
Name: "consul-mesh-gateway",
Expand Down

0 comments on commit e8d385b

Please sign in to comment.