Skip to content

Commit

Permalink
Add DFKE data source
Browse files Browse the repository at this point in the history
  • Loading branch information
ducvm29 committed Sep 17, 2024
1 parent 1248843 commit f06769e
Show file tree
Hide file tree
Showing 6 changed files with 370 additions and 8 deletions.
4 changes: 4 additions & 0 deletions commons/api_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var ApiPath = struct {
ListSubnets func(vpcId string) string

Subnet func(vpcId string) string
DedicatedFKEList func(vpcId string, page, pageSize int) string
DedicatedFKEGet func(vpcId string, clusterId string) string
DedicatedFKEUpgradeVersion func(vpcId string, clusterId string) string
DedicatedFKEManagement func(vpcId string, clusterId string) string
Expand Down Expand Up @@ -153,6 +154,9 @@ var ApiPath = struct {

Subnet: func(vpcId string) string { return fmt.Sprintf("/v1/vmware/vpc/%s/network/subnets", vpcId) },

DedicatedFKEList: func(vpcId string, page, pageSize int) string {
return fmt.Sprintf("/v1/xplat/fke/vpc/%s/kubernetes?page=%d&page_size=%d", vpcId, page, pageSize)
},
DedicatedFKEGet: func(vpcId string, clusterId string) string {
return fmt.Sprintf("/v1/xplat/fke/vpc/%s/cluster/%s?page=1&page_size=25", vpcId, clusterId)
},
Expand Down
296 changes: 296 additions & 0 deletions fptcloud/dfke/datasource_dfke.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
package fptcloud_dfke

import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
diag2 "github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"terraform-provider-fptcloud/commons"
)

var (
_ datasource.DataSource = &datasourceDedicatedKubernetesEngine{}
_ datasource.DataSourceWithConfigure = &datasourceDedicatedKubernetesEngine{}
)

type datasourceDedicatedKubernetesEngine struct {
client *commons.Client
dfkeClient *dfkeApiClient
tenancyApiClient *tenancyApiClient
}

func NewDataSourceDedicatedKubernetesEngine() datasource.DataSource {
return &datasourceDedicatedKubernetesEngine{}
}

func (d *datasourceDedicatedKubernetesEngine) Configure(ctx context.Context, request datasource.ConfigureRequest, response *datasource.ConfigureResponse) {
if request.ProviderData == nil {
return
}

client, ok := request.ProviderData.(*commons.Client)
if !ok {
response.Diagnostics.AddError(
"Unexpected Resource Configure Type",
fmt.Sprintf("Expected *commons.Client, got: %T. Please report this issue to the provider developers.", request.ProviderData),
)

return
}

d.client = client
a, err := newDfkeApiClient(client)
if err != nil {
response.Diagnostics.AddError(
"Error configuring API client",
fmt.Sprintf("%s", err.Error()),
)

return
}

d.dfkeClient = a

t := newTenancyApiClient(client)
d.tenancyApiClient = t
}

func (d *datasourceDedicatedKubernetesEngine) Metadata(ctx context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) {
response.TypeName = request.ProviderTypeName + "_dedicated_kubernetes_engine_v1"
}

func (d *datasourceDedicatedKubernetesEngine) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) {
response.Schema = schema.Schema{
Description: "Retrieves information about dedicated FKE clusters",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
},
"vpc_id": schema.StringAttribute{
Required: true,
},
"cluster_id": schema.StringAttribute{
Required: true,
Description: "Cluster ID, as shown on the dashboard, usually has a length of 8 characters",
},
"cluster_name": schema.StringAttribute{
Computed: true,
},
"k8s_version": schema.StringAttribute{
Computed: true,
},
"master_type": schema.StringAttribute{
Computed: true,
},
"master_count": schema.Int64Attribute{
Computed: true,
},
"master_disk_size": schema.Int64Attribute{
Computed: true,
},
"worker_type": schema.StringAttribute{
Computed: true,
},
"worker_disk_size": schema.Int64Attribute{
Computed: true,
},
"network_id": schema.StringAttribute{
Computed: true,
},
"lb_size": schema.StringAttribute{
Computed: true,
},
"pod_network": schema.StringAttribute{
Computed: true,
},
"service_network": schema.StringAttribute{
Computed: true,
},
"network_node_prefix": schema.Int64Attribute{
Computed: true,
},
"max_pod_per_node": schema.Int64Attribute{
Computed: true,
},
"nfs_status": schema.StringAttribute{
Computed: true,
},
"nfs_disk_size": schema.Int64Attribute{
Computed: true,
},
"storage_policy": schema.StringAttribute{
Computed: true,
},
"edge_id": schema.StringAttribute{
Computed: true,
},
"scale_min": schema.Int64Attribute{
Computed: true,
},
"scale_max": schema.Int64Attribute{
Computed: true,
},
"node_dns": schema.StringAttribute{
Computed: true,
},
"ip_public_firewall": schema.StringAttribute{
Computed: true,
},
"ip_private_firewall": schema.StringAttribute{
Computed: true,
},
"region_id": schema.StringAttribute{
Computed: true,
},
},
}
}

func (d *datasourceDedicatedKubernetesEngine) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) {
var state dedicatedKubernetesEngine
diags := request.Config.Get(ctx, &state)

response.Diagnostics.Append(diags...)
if response.Diagnostics.HasError() {
return
}

clusterId := state.ClusterId.ValueString()
uuid, err := d.findClusterUUID(ctx, state.vpcId(), clusterId)
if err != nil {
response.Diagnostics.Append(diag2.NewErrorDiagnostic("Error resolving cluster UUID", err.Error()))
return
}

_, err = d.internalRead(ctx, uuid, &state)
if err != nil {
response.Diagnostics.Append(diag2.NewErrorDiagnostic("Error calling API", err.Error()))
return
}

diags = response.State.Set(ctx, &state)
response.Diagnostics.Append(diags...)
if response.Diagnostics.HasError() {
return
}
}

func (d *datasourceDedicatedKubernetesEngine) internalRead(ctx context.Context, clusterId string, state *dedicatedKubernetesEngine) (*dedicatedKubernetesEngineReadResponse, error) {
vpcId := state.VpcId.ValueString()
tflog.Info(ctx, "Reading state of cluster ID "+clusterId+", VPC ID "+vpcId)

a, err := d.client.SendGetRequest(commons.ApiPath.DedicatedFKEGet(vpcId, clusterId))

if err != nil {
return nil, err
}

var readResponse dedicatedKubernetesEngineReadResponse
err = json.Unmarshal(a, &readResponse)
if err != nil {
tflog.Info(ctx, "Error unmarshalling cluster info for cluster "+clusterId)
return nil, err
}
data := readResponse.Cluster

var awx dedicatedKubernetesEngineParams
err = json.Unmarshal([]byte(data.AwxParams), &awx)

if err != nil {
tflog.Info(ctx, "Error unmarshalling AWX params for cluster "+clusterId)
tflog.Info(ctx, "AwxParams is "+data.AwxParams)
return nil, err
}

// resolve edge ID
edge, err := d.dfkeClient.FindEdgeByEdgeGatewayId(ctx, vpcId, data.EdgeID)
if err != nil {
return nil, err
}

state.ClusterId = types.StringValue(data.ClusterID)
state.ClusterName = types.StringValue(data.Name)
state.Version = types.StringValue(awx.K8SVersion)
state.MasterType = types.StringValue(awx.MasterType)
state.MasterCount = types.Int64Value(int64(awx.MasterCount))
state.MasterDiskSize = types.Int64Value(int64(awx.MasterDiskSize))
state.WorkerType = types.StringValue(awx.WorkerType)
state.WorkerDiskSize = types.Int64Value(int64(awx.WorkerDiskSize))
state.NetworkID = types.StringValue(data.NetworkID)
state.LbSize = types.StringValue(awx.LbSize)
state.PodNetwork = types.StringValue(awx.PodNetwork + "/" + awx.PodPrefix)
state.ServiceNetwork = types.StringValue(awx.ServiceNetwork + "/" + awx.ServicePrefix)
state.NetworkNodePrefix = types.Int64Value(int64(awx.NetworkNodePrefix))
state.MaxPodPerNode = types.Int64Value(int64(awx.K8SMaxPod))
state.NfsStatus = types.StringValue(awx.NfsStatus)
state.NfsDiskSize = types.Int64Value(int64(awx.NfsDiskSize))
state.StoragePolicy = types.StringValue(awx.StorageProfile)
state.EdgeID = types.StringValue(edge.Id)
state.ScaleMin = types.Int64Value(int64(awx.ScaleMinSize))
state.ScaleMax = types.Int64Value(int64(awx.ScaleMaxSize))
state.NodeDNS = types.StringValue(awx.NodeDNS)
state.IPPublicFirewall = types.StringValue(awx.IPPublicFirewall)
state.IPPrivateFirewall = types.StringValue(awx.IPPrivateFirewall)
state.VpcId = types.StringValue(data.VpcID)
//state.CustomScript = awx.CustomScript
//state.EnableCustomScript = awx.EnableCustomScript
region, err := getRegionFromVpcId(d.tenancyApiClient, ctx, vpcId)
if err != nil {
return nil, err
}
state.RegionId = types.StringValue(region)

return &readResponse, nil
}

func (d *datasourceDedicatedKubernetesEngine) findClusterUUID(ctx context.Context, vpcId string, clusterId string) (string, error) {
total := 1
found := 0

index := 1
for found < total {
path := commons.ApiPath.DedicatedFKEList(vpcId, index, 25)
data, err := d.client.SendGetRequest(path)
if err != nil {
return "", err
}

var list dedicatedKubernetesEngineList
err = json.Unmarshal(data, &list)
if err != nil {
return "", err
}

if list.Total == 0 {
return "", errors.New("no cluster with such ID found")
}

if len(list.Data) == 0 {
return "", errors.New("no cluster with such ID found")
}

total = list.Total
index += 1
for _, entry := range list.Data {
if entry.ClusterId == clusterId {
return entry.Id, nil
}
}
}

return "", errors.New("no cluster with such ID found")
}

type dedicatedKubernetesEngineList struct {
Data []struct {
ClusterName string `json:"cluster_name"`
ClusterId string `json:"cluster_id,omitempty"`
Id string `json:"id,omitempty"`
} `json:"data"`
Total int `json:"total"`
}
24 changes: 21 additions & 3 deletions fptcloud/dfke/dfke_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ type edgeResponse struct {
EdgeGateway EdgeGateway `json:"edgeGateway"`
}

type edgeListResponse struct {
Data []EdgeGateway `json:"data"`
}

func (a *dfkeApiClient) FindEdgeById(ctx context.Context, vpcId string, id string) (*EdgeGateway, error) {
tflog.Info(ctx, "Resolving edge by ID "+id)
path := fmt.Sprintf("/v1/kubernetes/vpc/%s/find_edge_by_id/%s/false", vpcId, id)
Expand All @@ -59,14 +63,28 @@ func (a *dfkeApiClient) FindEdgeByEdgeGatewayId(ctx context.Context, vpcId strin
if !strings.HasPrefix(edgeId, "urn:vcloud:gateway") {
return nil, errors.New("edge gateway id must be prefixed with \"urn:vcloud:gateway\"")
}

tflog.Info(ctx, "Resolving edge by gateway ID "+edgeId)
path := fmt.Sprintf("/v1/kubernetes/vpc/%s/find_edge_by_id/%s/true", vpcId, edgeId)
r, err := a.internalFindEdge(path)

path := fmt.Sprintf("/v1/vmware/vpc/%s/edge_gateway/list", vpcId)
r, err := a.edgeClient.SendGetRequest(path)
if err != nil {
return nil, err
}

return r, nil
var edgeList edgeListResponse
err = json.Unmarshal(r, &edgeList)
if err != nil {
return nil, err
}

for _, edge := range edgeList.Data {
if edge.EdgeGatewayId == edgeId {
return &edge, nil
}
}

return nil, errors.New("edge gateway not found")
}

func (a *dfkeApiClient) internalFindEdge(endpoint string) (*EdgeGateway, error) {
Expand Down
6 changes: 2 additions & 4 deletions fptcloud/dfke/resource_dfke.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ func (r *resourceDedicatedKubernetesEngine) internalRead(ctx context.Context, cl
state.VpcId = types.StringValue(data.VpcID)
//state.CustomScript = awx.CustomScript
//state.EnableCustomScript = awx.EnableCustomScript
region, err := r.getRegionFromVpcId(ctx, vpcId)
region, err := getRegionFromVpcId(r.tenancyApiClient, ctx, vpcId)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -746,9 +746,7 @@ func (e *dedicatedKubernetesEngine) vpcId() string {
func (e *dedicatedKubernetesEngine) clusterUUID() string {
return e.Id.ValueString()
}
func (r *resourceDedicatedKubernetesEngine) getRegionFromVpcId(ctx context.Context, vpcId string) (string, error) {
client := r.tenancyApiClient

func getRegionFromVpcId(client *tenancyApiClient, ctx context.Context, vpcId string) (string, error) {
t, err := client.GetTenancy(ctx)
if err != nil {
return "", err
Expand Down
4 changes: 3 additions & 1 deletion fptcloud/provider_tf6.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ func (x *xplatProvider) Configure(ctx context.Context, request provider.Configur
}

func (x *xplatProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{}
return []func() datasource.DataSource{
fptcloud_dfke.NewDataSourceDedicatedKubernetesEngine,
}
}

func (x *xplatProvider) Resources(ctx context.Context) []func() resource.Resource {
Expand Down
Loading

0 comments on commit f06769e

Please sign in to comment.