-
Notifications
You must be signed in to change notification settings - Fork 4
/
base_domain.go
150 lines (122 loc) · 3.55 KB
/
base_domain.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
148
149
150
package basedomain
import (
"context"
"reflect"
infrastructurev1alpha3 "github.com/giantswarm/apiextensions/v6/pkg/apis/infrastructure/v1alpha3"
providerv1alpha1 "github.com/giantswarm/apiextensions/v6/pkg/apis/provider/v1alpha1"
"github.com/giantswarm/k8sclient/v7/pkg/k8sclient"
"github.com/giantswarm/microerror"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/giantswarm/cluster-operator/v5/pkg/label"
"github.com/giantswarm/cluster-operator/v5/service/controller/key"
"github.com/giantswarm/cluster-operator/v5/service/internal/basedomain/internal/cache"
)
type Config struct {
K8sClient k8sclient.Interface
Provider string
}
type BaseDomain struct {
k8sClient k8sclient.Interface
clusterCache *cache.Cluster
provider string
}
func New(c Config) (*BaseDomain, error) {
if c.K8sClient == nil {
return nil, microerror.Maskf(invalidConfigError, "%T.K8sClient must not be empty", c)
}
if c.Provider == "" {
return nil, microerror.Maskf(invalidConfigError, "%T.Provider must not be empty", c)
}
bd := &BaseDomain{
k8sClient: c.K8sClient,
clusterCache: cache.NewCluster(),
provider: c.Provider,
}
return bd, nil
}
func (bd *BaseDomain) BaseDomain(ctx context.Context, obj interface{}) (string, error) {
cr, err := meta.Accessor(obj)
if err != nil {
return "", microerror.Mask(err)
}
cl, err := bd.cachedCluster(ctx, cr)
if err != nil {
return "", microerror.Mask(err)
}
aws, ok := cl.(infrastructurev1alpha3.AWSCluster)
if ok {
return aws.Spec.Cluster.DNS.Domain, nil
}
azure, ok := cl.(providerv1alpha1.AzureConfig)
if ok {
return azure.Spec.Azure.DNSZones.API.Name, nil
}
return "", microerror.Maskf(invalidTypeError, "Cached object was of invalid type %q", reflect.TypeOf(cl))
}
func (bd *BaseDomain) cachedCluster(ctx context.Context, cr metav1.Object) (interface{}, error) {
var err error
var ok bool
var cluster interface{}
{
ck := bd.clusterCache.Key(ctx, cr)
if ck == "" {
cluster, err = bd.lookupCluster(ctx, cr)
if err != nil {
return infrastructurev1alpha3.AWSCluster{}, microerror.Mask(err)
}
} else {
cluster, ok = bd.clusterCache.Get(ctx, ck)
if !ok {
cluster, err = bd.lookupCluster(ctx, cr)
if err != nil {
return infrastructurev1alpha3.AWSCluster{}, microerror.Mask(err)
}
bd.clusterCache.Set(ctx, ck, cluster)
}
}
}
return cluster, nil
}
func (bd *BaseDomain) lookupCluster(ctx context.Context, cr metav1.Object) (interface{}, error) {
switch bd.provider {
case label.ProviderAWS:
var list infrastructurev1alpha3.AWSClusterList
err := bd.k8sClient.CtrlClient().List(
ctx,
&list,
client.InNamespace(cr.GetNamespace()),
client.MatchingLabels{label.Cluster: key.ClusterID(cr)},
)
if err != nil {
return nil, microerror.Mask(err)
}
if len(list.Items) == 1 {
return list.Items[0], nil
}
if len(list.Items) > 1 {
return nil, microerror.Mask(tooManyCRsError)
}
case label.ProviderAzure:
var list providerv1alpha1.AzureConfigList
err := bd.k8sClient.CtrlClient().List(
ctx,
&list,
client.InNamespace("default"),
client.MatchingLabels{label.Cluster: key.ClusterID(cr)},
)
if err != nil {
return nil, microerror.Mask(err)
}
if len(list.Items) == 1 {
return list.Items[0], nil
}
if len(list.Items) > 1 {
return nil, microerror.Mask(tooManyCRsError)
}
default:
return nil, microerror.Maskf(unsupportedProviderError, "Provider %q is unsupported", bd.provider)
}
return nil, microerror.Mask(notFoundError)
}