Skip to content

Commit

Permalink
feat: kubernets connection from CNRM
Browse files Browse the repository at this point in the history
  • Loading branch information
adityathebe committed Nov 29, 2024
1 parent 94a8017 commit aad8067
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 25 deletions.
2 changes: 1 addition & 1 deletion connection/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func SetupConnection(ctx context.Context, connections ExecConnections, cmd *osEx
return nil, err
} else if found {
connections.Kubernetes = &KubernetesConnection{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(kubeconfig, &connections.Kubernetes.KubeConfig); err != nil {
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(kubeconfig, &connections.Kubernetes.Kubeconfig); err != nil {
return nil, err
}

Expand Down
108 changes: 87 additions & 21 deletions connection/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/aws/aws-sdk-go-v2/aws"
signerv4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
"github.com/aws/aws-sdk-go-v2/service/eks"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"

Expand All @@ -25,47 +27,111 @@ const (
v1Prefix = "k8s-aws-v1."
)

// +kubebuilder:object:generate=true
type KubeconfigConnection struct {
// Connection name to populate kubeconfig
ConnectionName string `json:"connection,omitempty"`
Kubeconfig *types.EnvVar `json:"kubeconfig,omitempty"`
}

func (t *KubeconfigConnection) Populate(ctx context.Context) (kubernetes.Interface, *rest.Config, error) {
if t.ConnectionName != "" {
connection, err := ctx.HydrateConnectionByURL(t.ConnectionName)
if err != nil {
return nil, nil, err
} else if connection == nil {
return nil, nil, fmt.Errorf("connection[%s] not found", t.ConnectionName)
}

t.Kubeconfig.ValueStatic = connection.Certificate
}

if t.Kubeconfig != nil {
if v, err := ctx.GetEnvValueFromCache(*t.Kubeconfig, ctx.GetNamespace()); err != nil {
return nil, nil, err
} else {
t.Kubeconfig.ValueStatic = v
}

return dutyKubernetes.NewClientFromPathOrConfig(ctx.Logger, t.Kubeconfig.ValueStatic)
}

return nil, nil, nil
}

// +kubebuilder:object:generate=true
type EKSConnection struct {
AWSConnection `json:",inline" yaml:",inline"`

Cluster string `json:"cluster"`
}

// +kubebuilder:object:generate=true
type CNRMConnection struct {
// TODO: is this how we want the users to connect to CNRM ?
KubeconfigConnection `json:",inline" yaml:",inline"`

Namespace string `json:"namespace"`
ContainerCluster string `json:"cluster"`
}

// +kubebuilder:object:generate=true
type KubernetesConnection struct {
ConnectionName string `json:"connection,omitempty"`
KubeConfig *types.EnvVar `json:"kubeconfig,omitempty"`
EKS *EKSConnection `json:"eks,omitempty"`
KubeconfigConnection `json:",inline"`

EKS *EKSConnection `json:"eks,omitempty"`
CNRM *CNRMConnection `json:"cnrm,omitempty"`
}

func (t KubernetesConnection) ToModel() models.Connection {
return models.Connection{
Type: models.ConnectionTypeKubernetes,
Certificate: t.KubeConfig.ValueStatic,
Certificate: t.Kubeconfig.ValueStatic,
}
}

func (t *KubernetesConnection) Populate(ctx context.Context) (kubernetes.Interface, *rest.Config, error) {
if t.ConnectionName != "" {
connection, err := ctx.HydrateConnectionByURL(t.ConnectionName)
if err != nil {
return nil, nil, err
} else if connection == nil {
return nil, nil, fmt.Errorf("connection[%s] not found", t.ConnectionName)
}

t.KubeConfig.ValueStatic = connection.Certificate
if clientset, restConfig, err := t.KubeconfigConnection.Populate(ctx); err != nil {
return nil, nil, nil
} else if clientset != nil {
return clientset, restConfig, nil
}

if t.KubeConfig != nil {
if v, err := ctx.GetEnvValueFromCache(*t.KubeConfig, ctx.GetNamespace()); err != nil {
return nil, nil, err
} else {
t.KubeConfig.ValueStatic = v
if t.CNRM != nil {
if clientset, restConfig, err := t.CNRM.KubeconfigConnection.Populate(ctx); err != nil {
return nil, nil, fmt.Errorf("failed to populate gcp connection: %w", err)
} else if clientset != nil {
containerClusterClient, err := dutyKubernetes.NewKubeClient(clientset, restConfig).GetClientByGroupVersionKind("container.cnrm.cloud.google.com", "v1beta1", "ContainerCluster")
if err != nil {
return nil, nil, fmt.Errorf("failed to create container CNRM cluster client: %w", err)
}

obj, err := containerClusterClient.Namespace(t.CNRM.Namespace).Get(ctx, t.CNRM.ContainerCluster, v1.GetOptions{})
if err != nil {
return nil, nil, fmt.Errorf("failed to get container cluster object(%s): %w", t.CNRM.ContainerCluster, err)
}

location, _, err := unstructured.NestedString(obj.Object, "spec", "location")
if err != nil {
return nil, nil, fmt.Errorf("failed to get location from container cluster spec: %w", err)
}

project, _, err := unstructured.NestedString(obj.Object, "metadata", "annotations", "cnrm.cloud.google.com/project-id")
if err != nil {
return nil, nil, fmt.Errorf("failed to get project from container cluster object: %w", err)
}

fmt.Println("location", location, "project", project)

// get the gcloud access token

// get the kubeconfig

// Set the token
}

return dutyKubernetes.NewClientFromPathOrConfig(ctx.Logger, t.KubeConfig.ValueStatic)
// we should get the

}

if t.EKS != nil {
Expand Down Expand Up @@ -128,7 +194,7 @@ func getEKSToken(ctx gocontext.Context, cluster string, conf aws.Config) (string
return "", fmt.Errorf("failed to retrive credentials from aws config: %w", err)
}

signedURI, err := getSignedURI(ctx, cluster, cred)
signedURI, err := getSignedSTSURI(ctx, cluster, cred)
if err != nil {
return "", fmt.Errorf("failed to get signed URI: %w", err)
}
Expand All @@ -137,7 +203,7 @@ func getEKSToken(ctx gocontext.Context, cluster string, conf aws.Config) (string
return token, nil
}

func getSignedURI(ctx gocontext.Context, cluster string, cred aws.Credentials) (string, error) {
func getSignedSTSURI(ctx gocontext.Context, cluster string, cred aws.Credentials) (string, error) {
request, err := http.NewRequest(http.MethodGet, "https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15", nil)
if err != nil {
return "", err
Expand Down
43 changes: 40 additions & 3 deletions connection/zz_generated.deepcopy.go

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

0 comments on commit aad8067

Please sign in to comment.