/
exported_services_types.go
147 lines (123 loc) · 4.64 KB
/
exported_services_types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package v2
import (
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2"
"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"
)
const (
exportedServicesKubeKind = "exportedservices"
)
func init() {
MultiClusterSchemeBuilder.Register(&ExportedServices{}, &ExportedServicesList{})
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// ExportedServices is the Schema for the Exported Services 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="Namespaced"
type ExportedServices struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec pbmulticluster.ExportedServices `json:"spec,omitempty"`
Status `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// ExportedServicesList contains a list of ExportedServices.
type ExportedServicesList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []*ExportedServices `json:"items"`
}
func (in *ExportedServices) ResourceID(_, partition string) *pbresource.ID {
return &pbresource.ID{
Name: in.Name,
Type: pbmulticluster.ExportedServicesType,
Tenancy: &pbresource.Tenancy{
Partition: partition,
Namespace: "", // Namespace is always unset because ExportedServices is partition-scoped
},
}
}
func (in *ExportedServices) Resource(namespace, partition string) *pbresource.Resource {
return &pbresource.Resource{
Id: in.ResourceID(namespace, partition),
Data: inject.ToProtoAny(&in.Spec),
Metadata: multiClusterConfigMeta(),
}
}
func (in *ExportedServices) AddFinalizer(f string) {
in.ObjectMeta.Finalizers = append(in.Finalizers(), f)
}
func (in *ExportedServices) RemoveFinalizer(f string) {
var newFinalizers []string
for _, oldF := range in.Finalizers() {
if oldF != f {
newFinalizers = append(newFinalizers, oldF)
}
}
in.ObjectMeta.Finalizers = newFinalizers
}
func (in *ExportedServices) Finalizers() []string {
return in.ObjectMeta.Finalizers
}
func (in *ExportedServices) 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) }),
)
}
func (in *ExportedServices) KubeKind() string {
return exportedServicesKubeKind
}
func (in *ExportedServices) KubernetesName() string {
return in.ObjectMeta.Name
}
func (in *ExportedServices) SetSyncedCondition(status corev1.ConditionStatus, reason, message string) {
in.Status.Conditions = Conditions{
{
Type: ConditionSynced,
Status: status,
LastTransitionTime: metav1.Now(),
Reason: reason,
Message: message,
},
}
}
func (in *ExportedServices) SetLastSyncedTime(time *metav1.Time) {
in.Status.LastSyncedTime = time
}
func (in *ExportedServices) 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
}
func (in *ExportedServices) SyncedConditionStatus() corev1.ConditionStatus {
condition := in.Status.GetCondition(ConditionSynced)
if condition == nil {
return corev1.ConditionUnknown
}
return condition.Status
}
func (in *ExportedServices) Validate(tenancy common.ConsulTenancyConfig) error {
// TODO add validation logic that ensures we only ever write this to the default namespace.
return nil
}
// DefaultNamespaceFields is required as part of the common.MeshConfig interface.
func (in *ExportedServices) DefaultNamespaceFields(tenancy common.ConsulTenancyConfig) {}