Skip to content

Commit

Permalink
feat(clouds): implement create function for Kubernetes cloud resource
Browse files Browse the repository at this point in the history
- Added `CreateKubernetesCloud` method in `kubernetesCloudsClient` to handle the creation of
  Kubernetes clouds.
- Integrated the new method into the Terraform provider's `Create` function in
  `kubernetesCloudResource`.
- Updated the schema and model to include necessary attributes for Kubernetes cloud creation.
  • Loading branch information
anvial committed Sep 27, 2024
1 parent c7d2617 commit f861c1a
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 16 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ require (
gopkg.in/httprequest.v1 v1.2.1
gopkg.in/macaroon.v2 v2.1.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/client-go v0.29.0
)

require (
Expand Down Expand Up @@ -223,7 +224,6 @@ require (
k8s.io/api v0.29.0 // indirect
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/apimachinery v0.29.0 // indirect
k8s.io/client-go v0.29.0 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/utils v0.0.0-20231127182322-b307cd553661 // indirect
Expand Down
59 changes: 57 additions & 2 deletions internal/juju/kubernetes_clouds.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@

package juju

import (
"github.com/juju/errors"
"github.com/juju/juju/api/client/cloud"
k8s "github.com/juju/juju/caas/kubernetes"
k8scloud "github.com/juju/juju/caas/kubernetes/cloud"
"k8s.io/client-go/tools/clientcmd"
)

type kubernetesCloudsClient struct {
SharedClient
}

type CreateKubernetesCloudInput struct {
Name string
KubernetesContextName string
KubernetesConfig string
ParentCloudName string
ParentCloudRegion string
}

type CreateKubernetesCloudOutput struct {
Expand All @@ -32,8 +45,50 @@ func newKubernetesCloudsClient(sc SharedClient) *kubernetesCloudsClient {
}

// CreateKubernetesCloud creates a new Kubernetes cloud with juju cloud facade.
func (c *kubernetesCloudsClient) CreateKubernetesCloud(input *CreateKubernetesCloudInput) (*CreateKubernetesCloudOutput, error) {
return nil, nil
func (c *kubernetesCloudsClient) CreateKubernetesCloud(input *CreateKubernetesCloudInput) error {
conn, err := c.GetConnection(nil)
if err != nil {
return err
}
defer func() { _ = conn.Close() }()

client := cloud.NewClient(conn)

conf, err := clientcmd.NewClientConfigFromBytes([]byte(input.KubernetesConfig))
if err != nil {
return errors.Annotate(err, "parsing kubernetes configuration data")
}

apiConf, err := conf.RawConfig()
if err != nil {
return errors.Annotate(err, "fetching kubernetes configuration")
}

var k8sContextName string
if input.KubernetesContextName == "" {
k8sContextName = apiConf.CurrentContext
} else {
k8sContextName = input.KubernetesContextName
}

newCloud, err := k8scloud.CloudFromKubeConfigContext(
k8sContextName,
&apiConf,
k8scloud.CloudParamaters{
Name: input.Name,
HostCloudRegion: k8s.K8sCloudOther,
},
)
if err != nil {
return errors.Trace(err)
}

err = client.AddCloud(newCloud, false)
if err != nil {
return errors.Annotate(err, "adding kubernetes cloud")
}

return nil
}

// ReadKubernetesCloud reads a Kubernetes cloud with juju cloud facade.
Expand Down
21 changes: 11 additions & 10 deletions internal/provider/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ const (
LogDataSourceOffer = "datasource-offer"
LogDataSourceSecret = "datasource-secret"

LogResourceApplication = "resource-application"
LogResourceAccessModel = "resource-assess-model"
LogResourceCredential = "resource-credential"
LogResourceMachine = "resource-machine"
LogResourceModel = "resource-model"
LogResourceOffer = "resource-offer"
LogResourceSSHKey = "resource-sshkey"
LogResourceUser = "resource-user"
LogResourceSecret = "resource-secret"
LogResourceAccessSecret = "resource-access-secret"
LogResourceApplication = "resource-application"
LogResourceAccessModel = "resource-assess-model"
LogResourceCredential = "resource-credential"
LogResourceKubernetesCloud = "resource-kubernetes-cloud"
LogResourceMachine = "resource-machine"
LogResourceModel = "resource-model"
LogResourceOffer = "resource-offer"
LogResourceSSHKey = "resource-sshkey"
LogResourceUser = "resource-user"
LogResourceSecret = "resource-secret"
LogResourceAccessSecret = "resource-access-secret"
)

const LogResourceIntegration = "resource-integration"
Expand Down
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ func (p *jujuProvider) Resources(_ context.Context) []func() resource.Resource {
func() resource.Resource { return NewApplicationResource() },
func() resource.Resource { return NewCredentialResource() },
func() resource.Resource { return NewIntegrationResource() },
func() resource.Resource { return NewKubernetesCloudResource() },
func() resource.Resource { return NewMachineResource() },
func() resource.Resource { return NewModelResource() },
func() resource.Resource { return NewOfferResource() },
Expand Down
51 changes: 48 additions & 3 deletions internal/provider/resource_kubernetes_cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ package provider

import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
Expand Down Expand Up @@ -34,12 +36,30 @@ type kubernetesCloudResource struct {

type kubernetesCloudResourceModel struct {
CloudName types.String `tfsdk:"name"`
KubeConfig types.String `tfsdk:"kubeconfig"`
KubernetesConfig types.String `tfsdk:"kubernetesconfig"`
ParentCloudName types.String `tfsdk:"parentcloudname"`
ParentCloudRegion types.String `tfsdk:"parentcloudregion"`
// ID required by the testing framework
ID types.String `tfsdk:"id"`
}

func (o *kubernetesCloudResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}

client, ok := req.ProviderData.(*juju.Client)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Resource Configure Type",
fmt.Sprintf("Expected *juju.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}
o.client = client
// Create the local logging subsystem here, using the TF context when creating it.
o.subCtx = tflog.NewSubsystem(ctx, LogResourceKubernetesCloud)
}

func (o *kubernetesCloudResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
Expand All @@ -61,8 +81,8 @@ func (o *kubernetesCloudResource) Schema(_ context.Context, req resource.SchemaR
stringplanmodifier.RequiresReplace(),
},
},
"kubeconfig": schema.StringAttribute{
Description: "The kubeconfig file path for the cloud.",
"kubernetesconfig": schema.StringAttribute{
Description: "The kubernetes config file path for the cloud.",
Optional: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
Expand Down Expand Up @@ -94,6 +114,31 @@ func (o *kubernetesCloudResource) Schema(_ context.Context, req resource.SchemaR

// Create adds a new kubernetes cloud to controllers used now by Terraform provider.
func (o *kubernetesCloudResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
// Prevent panic if the provider has not been configured.
if o.client == nil {
addClientNotConfiguredError(&resp.Diagnostics, "ssh_key", "create")
return
}

var plan kubernetesCloudResourceModel

// Read Terraform configuration from the request into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}

// Create the kubernetes cloud.
err := o.client.Clouds.CreateKubernetesCloud(
&juju.CreateKubernetesCloudInput{
Name: plan.CloudName.ValueString(),
KubernetesConfig: plan.KubernetesConfig.ValueString(),
},
)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create kubernetes cloud, got error %s", err))
return
}
}

// Read reads the current state of the kubernetes cloud.
Expand Down

0 comments on commit f861c1a

Please sign in to comment.