1 package services
2
3 import (
4 "context"
5 b64 "encoding/base64"
6 "errors"
7 "fmt"
8
9 clusterApi "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/container/v1beta1"
10 iamv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/iam/v1beta1"
11 resourceApi "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/resourcemanager/v1beta1"
12 helmApi "github.com/fluxcd/helm-controller/api/v2"
13 helmRepositoryApi "github.com/fluxcd/source-controller/api/v1"
14
15 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
16 utilruntime "k8s.io/apimachinery/pkg/util/runtime"
17 "k8s.io/client-go/kubernetes/scheme"
18 "k8s.io/client-go/rest"
19 "k8s.io/client-go/tools/clientcmd/api"
20 "sigs.k8s.io/controller-runtime/pkg/client"
21
22 "edge-infra.dev/pkg/edge/api/types"
23 "edge-infra.dev/pkg/edge/api/utils"
24
25 bannerAPI "edge-infra.dev/pkg/edge/apis/banner/v1alpha1"
26 edgeCluster "edge-infra.dev/pkg/edge/apis/cluster/v1alpha1"
27 gkeClusterApi "edge-infra.dev/pkg/edge/apis/gkecluster/v1alpha1"
28 )
29
30 func init() {
31 utilruntime.Must(edgeCluster.AddToScheme(scheme.Scheme))
32 utilruntime.Must(resourceApi.AddToScheme(scheme.Scheme))
33 utilruntime.Must(helmApi.AddToScheme(scheme.Scheme))
34 utilruntime.Must(helmRepositoryApi.AddToScheme(scheme.Scheme))
35 utilruntime.Must(clusterApi.AddToScheme(scheme.Scheme))
36 utilruntime.Must(apiextensionsv1.AddToScheme(scheme.Scheme))
37 utilruntime.Must(bannerAPI.AddToScheme(scheme.Scheme))
38 utilruntime.Must(clusterApi.AddToScheme(scheme.Scheme))
39 utilruntime.Must(gkeClusterApi.AddToScheme(scheme.Scheme))
40
41 utilruntime.Must(iamv1beta1.AddToScheme(scheme.Scheme))
42 }
43
44
45 type GkeClient interface {
46 GetConfigForCluster(ctx context.Context, cluster *types.GkeCluster) (*rest.Config, error)
47 GetRuntimeClient(ctx context.Context, cluster *types.GkeCluster) (client.WithWatch, error)
48 }
49
50 type gkeClient struct {
51
52 KubeConfig *rest.Config
53
54
55 RuntimeClient client.WithWatch
56
57
58 RuntimeClientMap map[string]client.WithWatch
59 }
60
61 func (gke *gkeClient) GetClientName(cluster *types.GkeCluster) string {
62 return fmt.Sprintf("%s-%s", cluster.Banner, cluster.Name)
63 }
64
65 func (gke *gkeClient) GetConfigForCluster(ctx context.Context, cluster *types.GkeCluster) (*rest.Config, error) {
66 singleResp := &clusterApi.ContainerCluster{}
67 key := client.ObjectKey{Namespace: cluster.Banner, Name: cluster.Name}
68 if err := gke.RuntimeClient.Get(ctx, key, singleResp); err != nil {
69 return nil, err
70 }
71 return getConfigForCluster(singleResp)
72 }
73
74 func getConfigForCluster(singleResp *clusterApi.ContainerCluster) (*rest.Config, error) {
75 if singleResp.Spec.MasterAuth == nil || singleResp.Spec.MasterAuth.ClusterCaCertificate == nil {
76 return nil, errors.New("ClusterCaCertificate not ready on kcc container cluster")
77 }
78 if singleResp.Status.Endpoint == nil {
79 return nil, errors.New("host not ready on kcc container cluster")
80 }
81 sDec, err := b64.StdEncoding.DecodeString(*singleResp.Spec.MasterAuth.ClusterCaCertificate)
82 if err != nil {
83 return nil, err
84 }
85 config := &rest.Config{
86 TLSClientConfig: rest.TLSClientConfig{
87 CAData: sDec,
88 },
89
90 Host: *singleResp.Status.Endpoint,
91 AuthProvider: &api.AuthProviderConfig{
92 Name: "gcp",
93 },
94 }
95 return config, nil
96 }
97
98 func (gke *gkeClient) GetRuntimeClient(ctx context.Context, cluster *types.GkeCluster) (client.WithWatch, error) {
99 if cluster == nil {
100 return gke.RuntimeClient, nil
101 }
102 name := gke.GetClientName(cluster)
103 if client, ok := gke.RuntimeClientMap[name]; ok {
104 return client, nil
105 }
106 cfg, err := gke.GetConfigForCluster(ctx, cluster)
107 if err != nil {
108 return nil, err
109 }
110 runtimeClient, err := client.NewWithWatch(cfg, client.Options{Scheme: scheme.Scheme})
111 if err != nil {
112 return nil, err
113 }
114 gke.RuntimeClientMap[name] = runtimeClient
115 return runtimeClient, nil
116 }
117
118 func NewGkeClient(masterconfig string) (*gkeClient, error) {
119 var err error
120 var config *rest.Config
121 var runtimeClient client.WithWatch
122
123 if masterconfig != "" {
124 if config, err = utils.GetKubeConfig(masterconfig); err != nil {
125 return nil, err
126 }
127 if runtimeClient, err = client.NewWithWatch(config, client.Options{Scheme: scheme.Scheme}); err != nil {
128 return nil, err
129 }
130 }
131 return &gkeClient{
132 KubeConfig: config,
133 RuntimeClient: runtimeClient,
134 RuntimeClientMap: map[string]client.WithWatch{},
135 }, nil
136 }
137
View as plain text