Allow specifying network ID in SKE cluster (#368)
This commit is contained in:
parent
e2e5f19a29
commit
ac0840fceb
6 changed files with 204 additions and 7 deletions
|
|
@ -228,6 +228,20 @@ func (r *clusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
|
|||
},
|
||||
},
|
||||
|
||||
"network": schema.SingleNestedAttribute{
|
||||
Description: "Network block as defined below.",
|
||||
Computed: true,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: "ID of the STACKIT Network Area (SNA) network into which the cluster will be deployed.",
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validate.UUID(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"hibernations": schema.ListNestedAttribute{
|
||||
Description: "One or more hibernation block as defined below.",
|
||||
Computed: true,
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ type Model struct {
|
|||
AllowPrivilegedContainers types.Bool `tfsdk:"allow_privileged_containers"`
|
||||
NodePools types.List `tfsdk:"node_pools"`
|
||||
Maintenance types.Object `tfsdk:"maintenance"`
|
||||
Network types.Object `tfsdk:"network"`
|
||||
Hibernations types.List `tfsdk:"hibernations"`
|
||||
Extensions types.Object `tfsdk:"extensions"`
|
||||
KubeConfig types.String `tfsdk:"kube_config"`
|
||||
|
|
@ -148,6 +149,16 @@ var maintenanceTypes = map[string]attr.Type{
|
|||
"end": basetypes.StringType{},
|
||||
}
|
||||
|
||||
// Struct corresponding to Model.Network
|
||||
type network struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
}
|
||||
|
||||
// Types corresponding to network
|
||||
var networkTypes = map[string]attr.Type{
|
||||
"id": basetypes.StringType{},
|
||||
}
|
||||
|
||||
// Struct corresponding to Model.Hibernations[i]
|
||||
type hibernation struct {
|
||||
Start types.String `tfsdk:"start"`
|
||||
|
|
@ -491,6 +502,22 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||
},
|
||||
},
|
||||
},
|
||||
"network": schema.SingleNestedAttribute{
|
||||
Description: "Network block as defined below.",
|
||||
Optional: true,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: "ID of the STACKIT Network Area (SNA) network into which the cluster will be deployed.",
|
||||
Optional: true,
|
||||
Validators: []validator.String{
|
||||
validate.UUID(),
|
||||
},
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"hibernations": schema.ListNestedAttribute{
|
||||
Description: "One or more hibernation block as defined below.",
|
||||
Optional: true,
|
||||
|
|
@ -731,6 +758,11 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag
|
|||
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating maintenance API payload: %v", err))
|
||||
return
|
||||
}
|
||||
network, err := toNetworkPayload(ctx, model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating network API payload: %v", err))
|
||||
return
|
||||
}
|
||||
hibernations, err := toHibernationsPayload(ctx, model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating hibernations API payload: %v", err))
|
||||
|
|
@ -747,6 +779,7 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag
|
|||
Hibernation: hibernations,
|
||||
Kubernetes: kubernetes,
|
||||
Maintenance: maintenance,
|
||||
Network: network,
|
||||
Nodepools: &nodePools,
|
||||
}
|
||||
_, err = r.client.CreateOrUpdateCluster(ctx, projectId, name).CreateOrUpdateClusterPayload(payload).Execute()
|
||||
|
|
@ -1174,6 +1207,22 @@ func toMaintenancePayload(ctx context.Context, m *Model) (*ske.Maintenance, erro
|
|||
}, nil
|
||||
}
|
||||
|
||||
func toNetworkPayload(ctx context.Context, m *Model) (*ske.V1Network, error) {
|
||||
if m.Network.IsNull() || m.Network.IsUnknown() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
network := network{}
|
||||
diags := m.Network.As(ctx, &network, basetypes.ObjectAsOptions{})
|
||||
if diags.HasError() {
|
||||
return nil, fmt.Errorf("converting network object: %v", diags.Errors())
|
||||
}
|
||||
|
||||
return &ske.V1Network{
|
||||
Id: conversion.StringValueToPointer(network.ID),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func mapFields(ctx context.Context, cl *ske.Cluster, m *Model) error {
|
||||
if cl == nil {
|
||||
return fmt.Errorf("response input is nil")
|
||||
|
|
@ -1206,19 +1255,23 @@ func mapFields(ctx context.Context, cl *ske.Cluster, m *Model) error {
|
|||
|
||||
err := mapNodePools(ctx, cl, m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mapping node_pools: %w", err)
|
||||
return fmt.Errorf("map node_pools: %w", err)
|
||||
}
|
||||
err = mapMaintenance(ctx, cl, m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mapping maintenance: %w", err)
|
||||
return fmt.Errorf("map maintenance: %w", err)
|
||||
}
|
||||
err = mapNetwork(cl, m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("map network: %w", err)
|
||||
}
|
||||
err = mapHibernations(cl, m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mapping hibernations: %w", err)
|
||||
return fmt.Errorf("map hibernations: %w", err)
|
||||
}
|
||||
err = mapExtensions(ctx, cl, m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mapping extensions: %w", err)
|
||||
return fmt.Errorf("map extensions: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1421,12 +1474,33 @@ func mapMaintenance(ctx context.Context, cl *ske.Cluster, m *Model) error {
|
|||
}
|
||||
maintenanceObject, diags := types.ObjectValue(maintenanceTypes, maintenanceValues)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("creating flavor: %w", core.DiagsToError(diags))
|
||||
return fmt.Errorf("create maintenance object: %w", core.DiagsToError(diags))
|
||||
}
|
||||
m.Maintenance = maintenanceObject
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapNetwork(cl *ske.Cluster, m *Model) error {
|
||||
if cl.Network == nil {
|
||||
m.Network = types.ObjectNull(networkTypes)
|
||||
return nil
|
||||
}
|
||||
|
||||
id := types.StringNull()
|
||||
if cl.Network.Id != nil {
|
||||
id = types.StringValue(*cl.Network.Id)
|
||||
}
|
||||
networkValues := map[string]attr.Value{
|
||||
"id": id,
|
||||
}
|
||||
networkObject, diags := types.ObjectValue(networkTypes, networkValues)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("create network object: %w", core.DiagsToError(diags))
|
||||
}
|
||||
m.Network = networkObject
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMaintenanceTimes(ctx context.Context, cl *ske.Cluster, m *Model) (startTime, endTime string, err error) {
|
||||
startTimeAPI, err := time.Parse(time.RFC3339, *cl.Maintenance.TimeWindow.Start)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ func TestMapFields(t *testing.T) {
|
|||
AllowPrivilegedContainers: types.BoolNull(),
|
||||
NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}),
|
||||
Maintenance: types.ObjectNull(maintenanceTypes),
|
||||
Network: types.ObjectNull(networkTypes),
|
||||
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
|
||||
Extensions: types.ObjectNull(extensionsTypes),
|
||||
KubeConfig: types.StringNull(),
|
||||
|
|
@ -92,6 +93,9 @@ func TestMapFields(t *testing.T) {
|
|||
End: utils.Ptr("0010-11-12T13:14:15Z"),
|
||||
},
|
||||
},
|
||||
Network: &ske.V1Network{
|
||||
Id: utils.Ptr("nid"),
|
||||
},
|
||||
Name: utils.Ptr("name"),
|
||||
Nodepools: &[]ske.Nodepool{
|
||||
{
|
||||
|
|
@ -194,6 +198,9 @@ func TestMapFields(t *testing.T) {
|
|||
"start": types.StringValue("03:04:05+06:00"),
|
||||
"end": types.StringValue("13:14:15Z"),
|
||||
}),
|
||||
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
|
||||
"id": types.StringValue("nid"),
|
||||
}),
|
||||
Hibernations: types.ListValueMust(
|
||||
types.ObjectType{AttrTypes: hibernationTypes},
|
||||
[]attr.Value{
|
||||
|
|
@ -223,6 +230,30 @@ func TestMapFields(t *testing.T) {
|
|||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil_network_id",
|
||||
types.ObjectNull(extensionsTypes),
|
||||
&ske.Cluster{
|
||||
Name: utils.Ptr("name"),
|
||||
Network: &ske.V1Network{},
|
||||
},
|
||||
Model{
|
||||
Id: types.StringValue("pid,name"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Name: types.StringValue("name"),
|
||||
KubernetesVersion: types.StringNull(),
|
||||
AllowPrivilegedContainers: types.BoolNull(),
|
||||
NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}),
|
||||
Maintenance: types.ObjectNull(maintenanceTypes),
|
||||
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
|
||||
"id": types.StringNull(),
|
||||
}),
|
||||
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
|
||||
Extensions: types.ObjectNull(extensionsTypes),
|
||||
KubeConfig: types.StringNull(),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"extensions_mixed_values",
|
||||
types.ObjectNull(extensionsTypes),
|
||||
|
|
@ -1936,3 +1967,63 @@ func TestGetLatestSupportedMachineVersion(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToNetworkPayload(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
model *Model
|
||||
expected *ske.V1Network
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"base",
|
||||
&Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Name: types.StringValue("name"),
|
||||
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
|
||||
"id": types.StringValue("nid"),
|
||||
}),
|
||||
},
|
||||
&ske.V1Network{
|
||||
Id: utils.Ptr("nid"),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"no_id",
|
||||
&Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Name: types.StringValue("name"),
|
||||
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
|
||||
"id": types.StringNull(),
|
||||
}),
|
||||
},
|
||||
&ske.V1Network{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"no_network",
|
||||
&Model{
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Name: types.StringValue("name"),
|
||||
Network: types.ObjectNull(networkTypes),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
payload, err := toNetworkPayload(context.Background(), tt.model)
|
||||
if !tt.isValid && err == nil {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
if tt.isValid {
|
||||
diff := cmp.Diff(payload, tt.expected)
|
||||
if diff != "" {
|
||||
t.Fatalf("Data does not match: %s", diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue