[NEED REFACTORING] added DynamicClient constructor to make API calls on CDRs

This commit is contained in:
pb 2025-04-11 12:00:21 +02:00
parent e4ecb8c1db
commit d5ad32e2e4

View File

@ -1,13 +1,11 @@
package infrastructure package infrastructure
import ( import (
"bytes"
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"html/template"
"oc-datacenter/conf" "oc-datacenter/conf"
"strings" "strings"
@ -16,13 +14,40 @@ import (
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
apply "k8s.io/client-go/applyconfigurations/core/v1" apply "k8s.io/client-go/applyconfigurations/core/v1"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
) )
var gvrSources = schema.GroupVersionResource{Group: "multicluster.admiralty.io", Version: "v1alpha1", Resource: "sources"}
var gvrTargets = schema.GroupVersionResource{Group: "multicluster.admiralty.io", Version: "v1alpha1", Resource: "targets"}
type KubernetesService struct { type KubernetesService struct {
Set *kubernetes.Clientset Set *kubernetes.Clientset
}
func NewDynamicClient() (*dynamic.DynamicClient, error) {
config := &rest.Config{
Host: conf.GetConfig().KubeHost + ":" + conf.GetConfig().KubePort,
TLSClientConfig: rest.TLSClientConfig{
CAData: []byte(conf.GetConfig().KubeCA),
CertData: []byte(conf.GetConfig().KubeCert),
KeyData: []byte(conf.GetConfig().KubeData),
},
}
dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
return nil, errors.New("Error creating Dynamic client: " + err.Error())
}
if dynamicClient == nil {
return nil, errors.New("Error creating Dynamic client: dynamicClient is nil")
}
return dynamicClient, nil
} }
func NewKubernetesService() (Infrastructure, error) { func NewKubernetesService() (Infrastructure, error) {
@ -34,6 +59,7 @@ func NewKubernetesService() (Infrastructure, error) {
KeyData: []byte(conf.GetConfig().KubeData), KeyData: []byte(conf.GetConfig().KubeData),
}, },
} }
// Create clientset // Create clientset
clientset, err := kubernetes.NewForConfig(config) clientset, err := kubernetes.NewForConfig(config)
fmt.Println("NewForConfig", clientset, err) fmt.Println("NewForConfig", clientset, err)
@ -44,6 +70,7 @@ func NewKubernetesService() (Infrastructure, error) {
return nil, errors.New("Error creating Kubernetes client: clientset is nil") return nil, errors.New("Error creating Kubernetes client: clientset is nil")
} }
return &KubernetesService{ return &KubernetesService{
Set: clientset, Set: clientset,
}, nil }, nil
@ -267,32 +294,73 @@ func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context,execut
return nil, nil // Maybe we could create a wrapper for errors and add more info to have return nil, nil // Maybe we could create a wrapper for errors and add more info to have
} }
var targetManifest string // var targetManifest string
var tpl bytes.Buffer // var tpl bytes.Buffer
tmpl, err := template.New("target"). // tmpl, err := template.New("target").
Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Target\", \"metadata\": {\"name\": \"target-{{.ExecutionId}}\"}, \"spec\": { \"kubeconfigSecret\" :{\"name\": \"kube-secret-{{.ExecutionId}}\"}} }") // Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Target\", \"metadata\": {\"name\": \"target-{{.ExecutionId}}\"}, \"spec\": { \"kubeconfigSecret\" :{\"name\": \"kube-secret-{{.ExecutionId}}\"}} }")
// if err != nil {
// fmt.Println("Error creating the template for the target Manifest")
// return nil, err
// }
// err = tmpl.Execute(&tpl, map[string]string{"ExecutionId":executionId})
// targetManifest = tpl.String()
// resp, err := putCDRapiKube(
// *k.Set,
// context,
// "/apis/multicluster.admiralty.io/v1alpha1/namespaces/"+ executionId +"/targets",
// []byte(targetManifest),
// map[string]string{"fieldManager":"kubectl-client-side-apply"},
// map[string]string{"fieldValidation":"Strict"},
// )
target := map[string]interface{}{
"apiVersion": "multicluster.admiralty.io/v1alpha1",
"kind": "Target",
"metadata": map[string]interface{}{
"name": "target-"+executionId,
"namespace": executionId,
},
"spec": map[string]interface{}{
"kubeconfigSecret": map[string]string{
"name" : "kube-secret-"+executionId,
},
},
}
body, err := json.Marshal(target)
if err != nil { if err != nil {
fmt.Println("Error creating the template for the target Manifest") fmt.Println("Error creating the body from the source Manifest")
return nil, err return nil, err
} }
err = tmpl.Execute(&tpl, map[string]string{"ExecutionId":executionId}) cli, err := NewDynamicClient()
targetManifest = tpl.String()
resp, err := putCDRapiKube(
*k.Set,
context,
"/apis/multicluster.admiralty.io/v1alpha1/namespaces/"+ executionId +"/targets",
[]byte(targetManifest),
map[string]string{"fieldManager":"kubectl-client-side-apply"},
map[string]string{"fieldValidation":"Strict"},
)
if err != nil { if err != nil {
fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", resp) return nil, errors.New("Could not retrieve dynamic client when creating Admiralty Source : " + err.Error())
}
res, err := cli.Resource(gvrTargets).
Namespace(executionId).
Apply(context,
"source-"+executionId,
&unstructured.Unstructured{Object: target},
metav1.ApplyOptions{
FieldManager: "kubectl-client-side-apply",
},
)
if err != nil {
fmt.Println("Error from k8s API when applying " + string(body) + " to " + gvrSources.String() + " : " , err)
return nil,err
}
resByte, err := json.Marshal(res)
if err != nil {
// fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", res)
return nil, err return nil, err
} }
return resp, nil return resByte, nil
} }
@ -305,35 +373,78 @@ func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context,execut
// to rather contact the oc-datacenter from the remote cluster to create the source // to rather contact the oc-datacenter from the remote cluster to create the source
// locally and retrieve the token for the serviceAccount // locally and retrieve the token for the serviceAccount
func (k *KubernetesService) CreateAdmiraltySource(context context.Context,executionId string) ([]byte, error) { func (k *KubernetesService) CreateAdmiraltySource(context context.Context,executionId string) ([]byte, error) {
var sourceManifest string // var sourceManifest string
var tpl bytes.Buffer // var tpl bytes.Buffer
tmpl, err := template.New("source"). // tmpl, err := template.New("source").
Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Source\", \"metadata\": {\"name\": \"source-{{.ExecutionId}}\"}, \"spec\": {\"serviceAccountName\": \"sa-{{.ExecutionId}}\"} }") // Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Source\", \"metadata\": {\"name\": \"source-{{.ExecutionId}}\"}, \"spec\": {\"serviceAccountName\": \"sa-{{.ExecutionId}}\"} }")
// if err != nil {
// fmt.Println("Error creating the template for the source Manifest")
// return nil, err
// }
source := map[string]interface{}{
"apiVersion": "multicluster.admiralty.io/v1alpha1",
"kind": "Source",
"metadata": map[string]interface{}{
"name": "source-"+executionId,
"namespace": executionId,
},
"spec": map[string]interface{}{
"serviceAccountName": "sa-"+executionId,
},
}
body, err := json.Marshal(source)
if err != nil { if err != nil {
fmt.Println("Error creating the template for the source Manifest") fmt.Println("Error creating the body from the source Manifest")
return nil, err return nil, err
} }
err = tmpl.Execute(&tpl, map[string]string{"ExecutionId":executionId}) // err = tmpl.Execute(&tpl, map[string]string{"ExecutionId":executionId})
sourceManifest = tpl.String() // sourceManifest = tpl.String()
// resp, err := putCDRapiKube(
// *k.Set,
// context,
// "/apis/multicluster.admiralty.io/v1alpha1/namespaces/"+ executionId +"/sources",
// []byte(sourceManifest),
// map[string]string{"fieldManager":"kubectl-client-side-apply"},
// map[string]string{"fieldValidation":"Strict"},
// )
// params := []map[string]string{
// {"fieldManager":"kubectl-client-side-apply"},
// {"fieldValidation":"Strict"},
// }
cli, err := NewDynamicClient()
if err != nil {
return nil, errors.New("Could not retrieve dynamic client when creating Admiralty Source : " + err.Error())
}
res, err := cli.Resource(gvrSources).
Namespace(executionId).
Apply(context,
"source-"+executionId,
&unstructured.Unstructured{Object: source},
metav1.ApplyOptions{
FieldManager: "kubectl-client-side-apply",
},
)
if err != nil {
fmt.Println("Error from k8s API when applying " + string(body) + " to " + gvrSources.String() + " : " , err)
return nil,err
}
resp, err := putCDRapiKube(
*k.Set,
context,
"/apis/multicluster.admiralty.io/v1alpha1/namespaces/"+ executionId +"/sources",
[]byte(sourceManifest),
map[string]string{"fieldManager":"kubectl-client-side-apply"},
map[string]string{"fieldValidation":"Strict"},
)
// We can add more info to the log with the content of resp if not nil // We can add more info to the log with the content of resp if not nil
resByte, err := json.Marshal(res)
if err != nil { if err != nil {
fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", resp) // fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", res)
return nil, err return nil, err
} }
return resp, nil return resByte, nil
} }
// Create a secret from a kubeconfing. Use it to create the secret binded to an Admiralty // Create a secret from a kubeconfing. Use it to create the secret binded to an Admiralty