diff --git a/akp/apis/v1alpha1/cluster.go b/akp/apis/v1alpha1/cluster.go
index b399f4c..d82ef82 100644
--- a/akp/apis/v1alpha1/cluster.go
+++ b/akp/apis/v1alpha1/cluster.go
@@ -25,11 +25,33 @@ type ClusterSpec struct {
Data ClusterData `json:"data,omitempty"`
}
+type Resources struct {
+ Mem string `json:"mem,omitempty"`
+ Cpu string `json:"cpu,omitempty"`
+}
+
type ManagedClusterConfig struct {
SecretName string `json:"secretName,omitempty"`
SecretKey string `json:"secretKey,omitempty"`
}
+type AutoScalerConfig struct {
+ ApplicationController *AppControllerAutoScalingConfig `json:"applicationController,omitempty"`
+ RepoServer *RepoServerAutoScalingConfig `json:"repoServer,omitempty"`
+}
+
+type AppControllerAutoScalingConfig struct {
+ ResourceMinimum *Resources `json:"resourceMinimum,omitempty"`
+ ResourceMaximum *Resources `json:"resourceMaximum,omitempty"`
+}
+
+type RepoServerAutoScalingConfig struct {
+ ResourceMinimum *Resources `json:"resourceMinimum,omitempty"`
+ ResourceMaximum *Resources `json:"resourceMaximum,omitempty"`
+ ReplicaMaximum int32 `json:"replicaMaximum,omitempty"`
+ ReplicaMinimum int32 `json:"replicaMinimum,omitempty"`
+}
+
type ClusterData struct {
Size ClusterSize `json:"size,omitempty"`
AutoUpgradeDisabled *bool `json:"autoUpgradeDisabled,omitempty"`
@@ -42,5 +64,6 @@ type ClusterData struct {
EksAddonEnabled *bool `json:"eksAddonEnabled,omitempty"`
ManagedClusterConfig *ManagedClusterConfig `json:"managedClusterConfig,omitempty"`
- MultiClusterK8SDashboardEnabled *bool `json:"multiClusterK8sDashboardEnabled,omitempty"`
+ MultiClusterK8SDashboardEnabled *bool `json:"multiClusterK8sDashboardEnabled,omitempty"`
+ AutoscalerConfig *AutoScalerConfig `json:"autoscalerConfig,omitempty"`
}
diff --git a/akp/data_source_akp_cluster.go b/akp/data_source_akp_cluster.go
index 4d06c00..7f4a2f7 100644
--- a/akp/data_source_akp_cluster.go
+++ b/akp/data_source_akp_cluster.go
@@ -54,7 +54,7 @@ func (d *AkpClusterDataSource) Read(ctx context.Context, req datasource.ReadRequ
return
}
ctx = httpctx.SetAuthorizationHeader(ctx, d.akpCli.Cred.Scheme(), d.akpCli.Cred.Credential())
- refreshClusterState(ctx, &resp.Diagnostics, d.akpCli.Cli, &data, d.akpCli.OrgId, &resp.State)
+ refreshClusterState(ctx, &resp.Diagnostics, d.akpCli.Cli, &data, d.akpCli.OrgId, &resp.State, &data)
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
diff --git a/akp/data_source_akp_cluster_schema.go b/akp/data_source_akp_cluster_schema.go
index f1db7bb..fa88752 100644
--- a/akp/data_source_akp_cluster_schema.go
+++ b/akp/data_source_akp_cluster_schema.go
@@ -81,7 +81,7 @@ func getClusterSpecDataSourceAttributes() map[string]schema.Attribute {
func getClusterDataDataSourceAttributes() map[string]schema.Attribute {
return map[string]schema.Attribute{
"size": schema.StringAttribute{
- MarkdownDescription: "Cluster Size. One of `small`, `medium` or `large`",
+ MarkdownDescription: "Cluster Size. One of `small`, `medium`, `large`, `custom` or `auto`",
Computed: true,
},
"auto_upgrade_disabled": schema.BoolAttribute{
@@ -121,6 +121,16 @@ func getClusterDataDataSourceAttributes() map[string]schema.Attribute {
MarkdownDescription: "Enable the KubeVision feature on the managed cluster",
Computed: true,
},
+ "auto_agent_size_config": schema.SingleNestedAttribute{
+ MarkdownDescription: "Autoscaler config for auto agent size",
+ Computed: true,
+ Attributes: getAutoScalerConfigDataSourceAttributes(),
+ },
+ "custom_agent_size_config": schema.SingleNestedAttribute{
+ MarkdownDescription: "Custom agent size config",
+ Computed: true,
+ Attributes: getCustomAgentSizeConfigDataSourceAttributes(),
+ },
}
}
@@ -201,3 +211,114 @@ func getManagedClusterConfigDataSourceAttributes() map[string]schema.Attribute {
},
}
}
+
+func getAutoScalerConfigDataSourceAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "application_controller": schema.SingleNestedAttribute{
+ Description: "Application Controller auto scaling config",
+ Computed: true,
+ Attributes: getAppControllerAutoScalingConfigDataSourceAttributes(),
+ },
+ "repo_server": schema.SingleNestedAttribute{
+ Description: "Repo Server auto scaling config",
+ Computed: true,
+ Attributes: getRepoServerAutoScalingConfigDataSourceAttributes(),
+ },
+ }
+}
+
+func getCustomAgentSizeConfigDataSourceAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "application_controller": schema.SingleNestedAttribute{
+ Description: "Application Controller custom agent size config",
+ Computed: true,
+ Attributes: getAppControllerCustomAgentSizeConfigDataSourceAttributes(),
+ },
+ "repo_server": schema.SingleNestedAttribute{
+ Description: "Repo Server custom agent size config",
+ Computed: true,
+ Attributes: getRepoServerCustomAgentSizeConfigDataSourceAttributes(),
+ },
+ }
+}
+
+func getAppControllerCustomAgentSizeConfigDataSourceAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "memory": schema.StringAttribute{
+ Description: "Memory",
+ Computed: true,
+ },
+ "cpu": schema.StringAttribute{
+ Description: "CPU",
+ Computed: true,
+ },
+ }
+}
+
+func getRepoServerCustomAgentSizeConfigDataSourceAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "memory": schema.StringAttribute{
+ Description: "Memory",
+ Computed: true,
+ },
+ "cpu": schema.StringAttribute{
+ Description: "CPU",
+ Computed: true,
+ },
+ "replicas": schema.Int64Attribute{
+ Description: "Replica",
+ Computed: true,
+ },
+ }
+}
+
+func getAppControllerAutoScalingConfigDataSourceAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "resource_minimum": schema.SingleNestedAttribute{
+ Description: "Resource minimum",
+ Computed: true,
+ Attributes: getResourcesDataSourceAttributes(),
+ },
+ "resource_maximum": schema.SingleNestedAttribute{
+ Description: "Resource maximum",
+ Computed: true,
+ Attributes: getResourcesDataSourceAttributes(),
+ },
+ }
+}
+
+func getRepoServerAutoScalingConfigDataSourceAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "resource_minimum": schema.SingleNestedAttribute{
+ Description: "Resource minimum",
+ Computed: true,
+ Attributes: getResourcesDataSourceAttributes(),
+ },
+ "resource_maximum": schema.SingleNestedAttribute{
+ Description: "Resource maximum",
+ Computed: true,
+ Attributes: getResourcesDataSourceAttributes(),
+ },
+ "replicas_maximum": schema.Int64Attribute{
+ Description: "Replica maximum",
+ Computed: true,
+ },
+ "replicas_minimum": schema.Int64Attribute{
+ Description: "Replica minimum",
+ Computed: true,
+ },
+ }
+}
+
+func getResourcesDataSourceAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "memory": schema.StringAttribute{
+ Description: "Memory",
+ Computed: true,
+ },
+ "cpu": schema.StringAttribute{
+ Description: "CPU",
+ Computed: true,
+ },
+ }
+}
diff --git a/akp/data_source_akp_clusters.go b/akp/data_source_akp_clusters.go
index a5bdab5..dabbb59 100644
--- a/akp/data_source_akp_clusters.go
+++ b/akp/data_source_akp_clusters.go
@@ -75,7 +75,7 @@ func (d *AkpClustersDataSource) Read(ctx context.Context, req datasource.ReadReq
stateCluster := types.Cluster{
InstanceID: data.InstanceID,
}
- stateCluster.Update(ctx, &resp.Diagnostics, cluster)
+ stateCluster.Update(ctx, &resp.Diagnostics, cluster, nil)
data.Clusters = append(data.Clusters, stateCluster)
}
// Save data into Terraform state
diff --git a/akp/resource_akp_cluster.go b/akp/resource_akp_cluster.go
index 4d5e971..2c5bde5 100644
--- a/akp/resource_akp_cluster.go
+++ b/akp/resource_akp_cluster.go
@@ -3,10 +3,11 @@ package akp
import (
"context"
"fmt"
- "github.com/pkg/errors"
"strings"
"time"
+ "github.com/pkg/errors"
+
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -95,7 +96,7 @@ func (r *AkpClusterResource) Read(ctx context.Context, req resource.ReadRequest,
}
ctx = httpctx.SetAuthorizationHeader(ctx, r.akpCli.Cred.Scheme(), r.akpCli.Cred.Credential())
- err := refreshClusterState(ctx, &resp.Diagnostics, r.akpCli.Cli, &data, r.akpCli.OrgId, &resp.State)
+ err := refreshClusterState(ctx, &resp.Diagnostics, r.akpCli.Cli, &data, r.akpCli.OrgId, &resp.State, &data)
if err != nil {
resp.Diagnostics.AddError("Client Error", err.Error())
} else {
@@ -186,12 +187,14 @@ func (r *AkpClusterResource) ImportState(ctx context.Context, req resource.Impor
func (r *AkpClusterResource) upsert(ctx context.Context, diagnostics *diag.Diagnostics, plan *types.Cluster, isCreate bool) (*types.Cluster, error) {
ctx = httpctx.SetAuthorizationHeader(ctx, r.akpCli.Cred.Scheme(), r.akpCli.Cred.Credential())
apiReq := buildClusterApplyRequest(ctx, diagnostics, plan, r.akpCli.OrgId)
+ if diagnostics.HasError() {
+ return nil, nil
+ }
result, err := r.applyInstance(ctx, plan, apiReq, isCreate, r.akpCli.Cli.ApplyInstance, r.upsertKubeConfig)
if err != nil {
return result, err
}
-
- return result, refreshClusterState(ctx, diagnostics, r.akpCli.Cli, result, r.akpCli.OrgId, nil)
+ return result, refreshClusterState(ctx, diagnostics, r.akpCli.Cli, result, r.akpCli.OrgId, nil, plan)
}
func (r *AkpClusterResource) applyInstance(ctx context.Context, plan *types.Cluster, apiReq *argocdv1.ApplyInstanceRequest, isCreate bool, applyInstance func(context.Context, *argocdv1.ApplyInstanceRequest) (*argocdv1.ApplyInstanceResponse, error), upsertKubeConfig func(ctx context.Context, plan *types.Cluster, isCreate bool) error) (*types.Cluster, error) {
@@ -240,7 +243,7 @@ func (r *AkpClusterResource) upsertKubeConfig(ctx context.Context, plan *types.C
}
func refreshClusterState(ctx context.Context, diagnostics *diag.Diagnostics, client argocdv1.ArgoCDServiceGatewayClient, cluster *types.Cluster,
- orgID string, state *tfsdk.State) error {
+ orgID string, state *tfsdk.State, plan *types.Cluster) error {
clusterReq := &argocdv1.GetInstanceClusterRequest{
OrganizationId: orgID,
InstanceId: cluster.InstanceID.ValueString(),
@@ -258,7 +261,7 @@ func refreshClusterState(ctx context.Context, diagnostics *diag.Diagnostics, cli
return errors.Wrap(err, "Unable to read Argo CD cluster")
}
tflog.Debug(ctx, fmt.Sprintf("Get cluster response: %s", clusterResp))
- cluster.Update(ctx, diagnostics, clusterResp.GetCluster())
+ cluster.Update(ctx, diagnostics, clusterResp.GetCluster(), plan)
return nil
}
diff --git a/akp/resource_akp_cluster_schema.go b/akp/resource_akp_cluster_schema.go
index d64d63b..2836ab8 100644
--- a/akp/resource_akp_cluster_schema.go
+++ b/akp/resource_akp_cluster_schema.go
@@ -9,8 +9,10 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -142,7 +144,7 @@ func getClusterSpecAttributes() map[string]schema.Attribute {
func getClusterDataAttributes() map[string]schema.Attribute {
return map[string]schema.Attribute{
"size": schema.StringAttribute{
- MarkdownDescription: "Cluster Size. One of `small`, `medium` or `large`",
+ MarkdownDescription: "Cluster Size. One of `small`, `medium`, `large`, `custom` or `auto`",
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
@@ -218,6 +220,17 @@ func getClusterDataAttributes() map[string]schema.Attribute {
boolplanmodifier.UseStateForUnknown(),
},
},
+ "auto_agent_size_config": schema.SingleNestedAttribute{
+ MarkdownDescription: "Autoscaler config for auto agent size",
+ Optional: true,
+ Computed: true,
+ Attributes: getAutoScalerConfigAttributes(),
+ },
+ "custom_agent_size_config": schema.SingleNestedAttribute{
+ MarkdownDescription: "Custom agent size config",
+ Optional: true,
+ Attributes: getCustomAgentSizeConfigAttributes(),
+ },
}
}
@@ -346,3 +359,174 @@ func getManagedClusterConfigAttributes() map[string]schema.Attribute {
},
}
}
+
+func getCustomAgentSizeConfigAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "application_controller": schema.SingleNestedAttribute{
+ Description: "Application Controller custom agent size config",
+ Optional: true,
+ Attributes: getAppControllerCustomAgentSizeConfigAttributes(),
+ },
+ "repo_server": schema.SingleNestedAttribute{
+ Description: "Repo Server custom agent size config",
+ Optional: true,
+ Attributes: getRepoServerCustomAgentSizeConfigAttributes(),
+ },
+ }
+}
+
+func getAppControllerCustomAgentSizeConfigAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "cpu": schema.StringAttribute{
+ Description: "CPU",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "memory": schema.StringAttribute{
+ Description: "Memory",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ }
+}
+
+func getRepoServerCustomAgentSizeConfigAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "cpu": schema.StringAttribute{
+ Description: "CPU",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "memory": schema.StringAttribute{
+ Description: "Memory",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "replicas": schema.Int64Attribute{
+ Description: "Replica",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Int64{
+ int64planmodifier.UseStateForUnknown(),
+ },
+ },
+ }
+}
+
+func getAutoScalerConfigAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "application_controller": schema.SingleNestedAttribute{
+ Description: "Application Controller auto scaling config",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Object{
+ objectplanmodifier.UseStateForUnknown(),
+ },
+ Attributes: getAppControllerAutoScalingConfigAttributes(),
+ },
+ "repo_server": schema.SingleNestedAttribute{
+ Description: "Repo Server auto scaling config",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Object{
+ objectplanmodifier.UseStateForUnknown(),
+ },
+ Attributes: getRepoServerAutoScalingConfigAttributes(),
+ },
+ }
+}
+
+func getAppControllerAutoScalingConfigAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "resource_minimum": schema.SingleNestedAttribute{
+ Description: "Resource minimum",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Object{
+ objectplanmodifier.UseStateForUnknown(),
+ },
+ Attributes: getResourcesAttributes(),
+ },
+ "resource_maximum": schema.SingleNestedAttribute{
+ Description: "Resource maximum",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Object{
+ objectplanmodifier.UseStateForUnknown(),
+ },
+ Attributes: getResourcesAttributes(),
+ },
+ }
+}
+
+func getRepoServerAutoScalingConfigAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "resource_minimum": schema.SingleNestedAttribute{
+ Description: "Resource minimum",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Object{
+ objectplanmodifier.UseStateForUnknown(),
+ },
+ Attributes: getResourcesAttributes(),
+ },
+ "resource_maximum": schema.SingleNestedAttribute{
+ Description: "Resource maximum",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Object{
+ objectplanmodifier.UseStateForUnknown(),
+ },
+ Attributes: getResourcesAttributes(),
+ },
+ "replicas_maximum": schema.Int64Attribute{
+ Description: "Replica maximum",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Int64{
+ int64planmodifier.UseStateForUnknown(),
+ },
+ },
+ "replicas_minimum": schema.Int64Attribute{
+ Description: "Replica minimum, this should be set to 1 as a minimum",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Int64{
+ int64planmodifier.UseStateForUnknown(),
+ },
+ },
+ }
+}
+
+func getResourcesAttributes() map[string]schema.Attribute {
+ return map[string]schema.Attribute{
+ "cpu": schema.StringAttribute{
+ Description: "CPU",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "memory": schema.StringAttribute{
+ Description: "Memory",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ }
+}
diff --git a/akp/resource_akp_cluster_test.go b/akp/resource_akp_cluster_test.go
index 05a3c67..75b273e 100644
--- a/akp/resource_akp_cluster_test.go
+++ b/akp/resource_akp_cluster_test.go
@@ -3,15 +3,16 @@ package akp
import (
"context"
"fmt"
- argocdv1 "github.com/akuity/api-client-go/pkg/api/gen/argocd/v1"
- "github.com/akuity/terraform-provider-akp/akp/types"
- hashitype "github.com/hashicorp/terraform-plugin-framework/types"
- "github.com/pkg/errors"
- "github.com/stretchr/testify/assert"
"testing"
+ hashitype "github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+
+ argocdv1 "github.com/akuity/api-client-go/pkg/api/gen/argocd/v1"
+ "github.com/akuity/terraform-provider-akp/akp/types"
)
func TestAccClusterResource(t *testing.T) {
diff --git a/akp/types/cluster.go b/akp/types/cluster.go
index bb1f3ad..e97a826 100644
--- a/akp/types/cluster.go
+++ b/akp/types/cluster.go
@@ -7,6 +7,7 @@ package types
import (
"github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
)
type Cluster struct {
@@ -33,20 +34,60 @@ type ClusterSpec struct {
Data ClusterData `tfsdk:"data"`
}
+type Resources struct {
+ Memory types.String `tfsdk:"memory"`
+ Cpu types.String `tfsdk:"cpu"`
+}
+
type ManagedClusterConfig struct {
SecretName types.String `tfsdk:"secret_name"`
SecretKey types.String `tfsdk:"secret_key"`
}
+type AutoScalerConfig struct {
+ ApplicationController *AppControllerAutoScalingConfig `tfsdk:"application_controller"`
+ RepoServer *RepoServerAutoScalingConfig `tfsdk:"repo_server"`
+}
+
+type AppControllerAutoScalingConfig struct {
+ ResourceMinimum *Resources `tfsdk:"resource_minimum"`
+ ResourceMaximum *Resources `tfsdk:"resource_maximum"`
+}
+
+type RepoServerAutoScalingConfig struct {
+ ResourceMinimum *Resources `tfsdk:"resource_minimum"`
+ ResourceMaximum *Resources `tfsdk:"resource_maximum"`
+ ReplicasMaximum types.Int64 `tfsdk:"replicas_maximum"`
+ ReplicasMinimum types.Int64 `tfsdk:"replicas_minimum"`
+}
+
+type CustomAgentSizeConfig struct {
+ ApplicationController *AppControllerCustomAgentSizeConfig `tfsdk:"application_controller"`
+ RepoServer *RepoServerCustomAgentSizeConfig `tfsdk:"repo_server"`
+}
+
+type AppControllerCustomAgentSizeConfig struct {
+ Memory types.String `tfsdk:"memory"`
+ Cpu types.String `tfsdk:"cpu"`
+}
+
+type RepoServerCustomAgentSizeConfig struct {
+ Memory types.String `tfsdk:"memory"`
+ Cpu types.String `tfsdk:"cpu"`
+ Replicas types.Int64 `tfsdk:"replicas"`
+}
+
type ClusterData struct {
- Size types.String `tfsdk:"size"`
- AutoUpgradeDisabled types.Bool `tfsdk:"auto_upgrade_disabled"`
- Kustomization types.String `tfsdk:"kustomization"`
- AppReplication types.Bool `tfsdk:"app_replication"`
- TargetVersion types.String `tfsdk:"target_version"`
- RedisTunneling types.Bool `tfsdk:"redis_tunneling"`
- DatadogAnnotationsEnabled types.Bool `tfsdk:"datadog_annotations_enabled"`
- EksAddonEnabled types.Bool `tfsdk:"eks_addon_enabled"`
- ManagedClusterConfig *ManagedClusterConfig `tfsdk:"managed_cluster_config"`
- MultiClusterK8SDashboardEnabled types.Bool `tfsdk:"multi_cluster_k8s_dashboard_enabled"`
+ Size types.String `tfsdk:"size"`
+ AutoUpgradeDisabled types.Bool `tfsdk:"auto_upgrade_disabled"`
+ Kustomization types.String `tfsdk:"kustomization"`
+ AppReplication types.Bool `tfsdk:"app_replication"`
+ TargetVersion types.String `tfsdk:"target_version"`
+ RedisTunneling types.Bool `tfsdk:"redis_tunneling"`
+ DatadogAnnotationsEnabled types.Bool `tfsdk:"datadog_annotations_enabled"`
+ EksAddonEnabled types.Bool `tfsdk:"eks_addon_enabled"`
+ ManagedClusterConfig *ManagedClusterConfig `tfsdk:"managed_cluster_config"`
+ MultiClusterK8SDashboardEnabled types.Bool `tfsdk:"multi_cluster_k8s_dashboard_enabled"`
+ AutoscalerConfig basetypes.ObjectValue `tfsdk:"auto_agent_size_config"`
+ CustomAgentSizeConfig *CustomAgentSizeConfig `tfsdk:"custom_agent_size_config"`
}
diff --git a/akp/types/types.go b/akp/types/types.go
index 10bb643..79b2ff3 100644
--- a/akp/types/types.go
+++ b/akp/types/types.go
@@ -12,8 +12,11 @@ import (
tftypes "github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"google.golang.org/protobuf/types/known/structpb"
+ appsv1 "k8s.io/api/apps/v1"
+ "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
+ kustomizetypes "sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
argocdv1 "github.com/akuity/api-client-go/pkg/api/gen/argocd/v1"
@@ -38,6 +41,7 @@ var (
argocdv1.ClusterSize_CLUSTER_SIZE_SMALL: "small",
argocdv1.ClusterSize_CLUSTER_SIZE_MEDIUM: "medium",
argocdv1.ClusterSize_CLUSTER_SIZE_LARGE: "large",
+ argocdv1.ClusterSize_CLUSTER_SIZE_AUTO: "auto",
argocdv1.ClusterSize_CLUSTER_SIZE_UNSPECIFIED: "unspecified",
}
)
@@ -139,7 +143,7 @@ func (a *ArgoCD) ToArgoCDAPIModel(ctx context.Context, diag *diag.Diagnostics, n
}
}
-func (c *Cluster) Update(ctx context.Context, diagnostics *diag.Diagnostics, apiCluster *argocdv1.Cluster) {
+func (c *Cluster) Update(ctx context.Context, diagnostics *diag.Diagnostics, apiCluster *argocdv1.Cluster, plan *Cluster) {
c.ID = tftypes.StringValue(apiCluster.GetId())
c.Name = tftypes.StringValue(apiCluster.GetName())
c.Namespace = tftypes.StringValue(apiCluster.GetNamespace())
@@ -182,13 +186,91 @@ func (c *Cluster) Update(ctx context.Context, diagnostics *diag.Diagnostics, api
}
}
+ var existingConfig kustomizetypes.Kustomization
+ size := tftypes.StringValue(ClusterSizeString[apiCluster.GetData().GetSize()])
+ var customConfig *CustomAgentSizeConfig
+ if err := yaml.Unmarshal(yamlData, &existingConfig); err == nil && plan != nil && plan.Spec != nil && plan.Spec.Data.CustomAgentSizeConfig != nil {
+ extractedCustomConfig := extractCustomSizeConfig(existingConfig)
+ if extractedCustomConfig != nil {
+ if plan != nil && plan.Spec != nil && plan.Spec.Data.CustomAgentSizeConfig != nil {
+ if areCustomAgentConfigsEquivalent(plan.Spec.Data.CustomAgentSizeConfig, extractedCustomConfig) {
+ customConfig = plan.Spec.Data.CustomAgentSizeConfig
+ } else {
+ customConfig = plan.Spec.Data.CustomAgentSizeConfig
+ }
+ existingConfig.Patches = filterNonSizePatchesKustomize(existingConfig.Patches)
+ existingConfig.Replicas = filterNonRepoServerReplicasKustomize(existingConfig.Replicas)
+ } else {
+ customConfig = extractedCustomConfig
+ }
+
+ if existingConfig.CheckEmpty() != nil {
+ kustomization = tftypes.StringValue("{}\n")
+ }
+
+ cleanYamlData, err := yaml.Marshal(existingConfig)
+ if err != nil {
+ diagnostics.AddError("failed to marshal cleaned config to yaml", err.Error())
+ } else {
+ kustomization = tftypes.StringValue(string(cleanYamlData))
+ }
+ size = tftypes.StringValue("custom")
+ }
+ }
+
c.Labels = labels
c.Annotations = annotations
+
+ var autoscalerConfig basetypes.ObjectValue
+ if c.Spec != nil && plan != nil {
+ newAPIConfig := apiCluster.GetData().GetAutoscalerConfig()
+ if !plan.Spec.Data.AutoscalerConfig.IsNull() && !plan.Spec.Data.AutoscalerConfig.IsUnknown() && newAPIConfig != nil &&
+ newAPIConfig.RepoServer != nil && newAPIConfig.ApplicationController != nil {
+ autoscalerConfig = plan.Spec.Data.AutoscalerConfig
+ newConfig := &AutoScalerConfig{
+ ApplicationController: &AppControllerAutoScalingConfig{
+ ResourceMinimum: &Resources{
+ Memory: tftypes.StringValue(newAPIConfig.ApplicationController.ResourceMinimum.Mem),
+ Cpu: tftypes.StringValue(newAPIConfig.ApplicationController.ResourceMinimum.Cpu),
+ },
+ ResourceMaximum: &Resources{
+ Memory: tftypes.StringValue(newAPIConfig.ApplicationController.ResourceMaximum.Mem),
+ Cpu: tftypes.StringValue(newAPIConfig.ApplicationController.ResourceMaximum.Cpu),
+ },
+ },
+ RepoServer: &RepoServerAutoScalingConfig{
+ ResourceMinimum: &Resources{
+ Memory: tftypes.StringValue(newAPIConfig.RepoServer.ResourceMinimum.Mem),
+ Cpu: tftypes.StringValue(newAPIConfig.RepoServer.ResourceMinimum.Cpu),
+ },
+ ResourceMaximum: &Resources{
+ Memory: tftypes.StringValue(newAPIConfig.RepoServer.ResourceMaximum.Mem),
+ Cpu: tftypes.StringValue(newAPIConfig.RepoServer.ResourceMaximum.Cpu),
+ },
+ ReplicasMaximum: tftypes.Int64Value(int64(newAPIConfig.RepoServer.ReplicaMaximum)),
+ ReplicasMinimum: tftypes.Int64Value(int64(newAPIConfig.RepoServer.ReplicaMinimum)),
+ },
+ }
+ if areAutoScalerConfigsEquivalent(extractConfigFromObjectValue(plan.Spec.Data.AutoscalerConfig), newConfig) {
+ autoscalerConfig = plan.Spec.Data.AutoscalerConfig
+ } else {
+ autoscalerConfig = toAutoScalerConfigTFModel(newAPIConfig)
+ }
+ } else {
+ autoscalerConfig = toAutoScalerConfigTFModel(newAPIConfig)
+ }
+ } else {
+ if plan == nil || plan.Spec == nil || plan.Spec.Data.AutoscalerConfig.IsNull() {
+ autoscalerConfig = basetypes.ObjectValue{}
+ }
+ autoscalerConfig = toAutoScalerConfigTFModel(apiCluster.GetData().GetAutoscalerConfig())
+ }
+
c.Spec = &ClusterSpec{
Description: tftypes.StringValue(apiCluster.GetDescription()),
NamespaceScoped: tftypes.BoolValue(apiCluster.GetNamespaceScoped()),
Data: ClusterData{
- Size: tftypes.StringValue(ClusterSizeString[apiCluster.GetData().GetSize()]),
+ Size: size,
AutoUpgradeDisabled: tftypes.BoolValue(apiCluster.GetData().GetAutoUpgradeDisabled()),
Kustomization: kustomization,
AppReplication: tftypes.BoolValue(apiCluster.GetData().GetAppReplication()),
@@ -198,6 +280,8 @@ func (c *Cluster) Update(ctx context.Context, diagnostics *diag.Diagnostics, api
EksAddonEnabled: tftypes.BoolValue(apiCluster.GetData().GetEksAddonEnabled()),
ManagedClusterConfig: toManagedClusterConfigTFModel(apiCluster.GetData().GetManagedClusterConfig()),
MultiClusterK8SDashboardEnabled: tftypes.BoolValue(apiCluster.GetData().GetMultiClusterK8SDashboardEnabled()),
+ AutoscalerConfig: autoscalerConfig,
+ CustomAgentSizeConfig: customConfig,
},
}
}
@@ -221,7 +305,7 @@ func (c *Cluster) ToClusterAPIModel(ctx context.Context, diagnostics *diag.Diagn
Spec: v1alpha1.ClusterSpec{
Description: c.Spec.Description.ValueString(),
NamespaceScoped: c.Spec.NamespaceScoped.ValueBool(),
- Data: toClusterDataAPIModel(diagnostics, c.Spec.Data),
+ Data: toClusterDataAPIModel(ctx, diagnostics, c.Spec.Data),
},
}
}
@@ -285,10 +369,19 @@ func ToConfigManagementPluginsTFModel(ctx context.Context, diagnostics *diag.Dia
return newCMPs
}
-func toClusterDataAPIModel(diagnostics *diag.Diagnostics, clusterData ClusterData) v1alpha1.ClusterData {
- raw := runtime.RawExtension{}
- if err := yaml.Unmarshal([]byte(clusterData.Kustomization.ValueString()), &raw); err != nil {
- diagnostics.AddError("failed unmarshal kustomization string to yaml", err.Error())
+func toClusterDataAPIModel(ctx context.Context, diagnostics *diag.Diagnostics, clusterData ClusterData) v1alpha1.ClusterData {
+ var autoscalerConfig *AutoScalerConfig
+ if d := clusterData.AutoscalerConfig.As(ctx, &autoscalerConfig, basetypes.ObjectAsOptions{
+ UnhandledNullAsEmpty: true,
+ UnhandledUnknownAsEmpty: true,
+ }); d.HasError() {
+ diagnostics.AddError("failed to convert autoscaler config", "")
+ return v1alpha1.ClusterData{}
+ }
+
+ size, raw := handleAgentSizeAndKustomization(diagnostics, &clusterData, autoscalerConfig)
+ if diagnostics.HasError() {
+ return v1alpha1.ClusterData{}
}
var managedConfig *v1alpha1.ManagedClusterConfig
@@ -299,8 +392,76 @@ func toClusterDataAPIModel(diagnostics *diag.Diagnostics, clusterData ClusterDat
}
}
+ autoscalerConfigAPI := &v1alpha1.AutoScalerConfig{}
+ if autoscalerConfig != nil {
+ if autoscalerConfig.RepoServer != nil {
+ if autoscalerConfig.RepoServer.ResourceMaximum == nil || autoscalerConfig.RepoServer.ResourceMinimum == nil {
+ diagnostics.AddError("repo server autoscaler config requires minimum and maximum resources", "")
+ return v1alpha1.ClusterData{}
+ }
+ if autoscalerConfig.RepoServer.ResourceMinimum.Memory.ValueString() == "" || autoscalerConfig.RepoServer.ResourceMinimum.Cpu.ValueString() == "" ||
+ autoscalerConfig.RepoServer.ResourceMaximum.Memory.ValueString() == "" || autoscalerConfig.RepoServer.ResourceMaximum.Cpu.ValueString() == "" ||
+ autoscalerConfig.RepoServer.ReplicasMaximum.ValueInt64() == 0 || autoscalerConfig.RepoServer.ReplicasMinimum.ValueInt64() == 0 {
+ diagnostics.AddError("repo server autoscaler config requires memory, cpu, and replicas values", "")
+ return v1alpha1.ClusterData{}
+ }
+ if !areResourcesValid(
+ autoscalerConfig.RepoServer.ResourceMinimum.Memory.ValueString(),
+ autoscalerConfig.RepoServer.ResourceMaximum.Memory.ValueString(),
+ ) {
+ diagnostics.AddError("repo server minimum memory must be less than or equal to maximum memory", "")
+ return v1alpha1.ClusterData{}
+ }
+ if !areResourcesValid(
+ autoscalerConfig.RepoServer.ResourceMinimum.Cpu.ValueString(),
+ autoscalerConfig.RepoServer.ResourceMaximum.Cpu.ValueString(),
+ ) {
+ diagnostics.AddError("repo server minimum CPU must be less than or equal to maximum CPU", "")
+ return v1alpha1.ClusterData{}
+ }
+ if autoscalerConfig.RepoServer.ReplicasMinimum.ValueInt64() > autoscalerConfig.RepoServer.ReplicasMaximum.ValueInt64() {
+ diagnostics.AddError("repo server minimum replicas must be less than or equal to maximum replicas", "")
+ return v1alpha1.ClusterData{}
+ }
+ autoscalerConfigAPI.RepoServer = &v1alpha1.RepoServerAutoScalingConfig{
+ ResourceMinimum: toResourcesAPIModel(autoscalerConfig.RepoServer.ResourceMinimum),
+ ResourceMaximum: toResourcesAPIModel(autoscalerConfig.RepoServer.ResourceMaximum),
+ ReplicaMaximum: int32(autoscalerConfig.RepoServer.ReplicasMaximum.ValueInt64()),
+ ReplicaMinimum: int32(autoscalerConfig.RepoServer.ReplicasMinimum.ValueInt64()),
+ }
+ }
+ if autoscalerConfig.ApplicationController != nil {
+ if autoscalerConfig.ApplicationController.ResourceMaximum == nil || autoscalerConfig.ApplicationController.ResourceMinimum == nil {
+ diagnostics.AddError("app controller autoscaler config requires minimum and maximum resources", "")
+ return v1alpha1.ClusterData{}
+ }
+ if autoscalerConfig.ApplicationController.ResourceMinimum.Memory.ValueString() == "" || autoscalerConfig.ApplicationController.ResourceMinimum.Cpu.ValueString() == "" ||
+ autoscalerConfig.ApplicationController.ResourceMaximum.Memory.ValueString() == "" || autoscalerConfig.ApplicationController.ResourceMaximum.Cpu.ValueString() == "" {
+ diagnostics.AddError("app controller autoscaler config requires memory, cpu values", "")
+ return v1alpha1.ClusterData{}
+ }
+ if !areResourcesValid(
+ autoscalerConfig.ApplicationController.ResourceMinimum.Memory.ValueString(),
+ autoscalerConfig.ApplicationController.ResourceMaximum.Memory.ValueString(),
+ ) {
+ diagnostics.AddError("application controller minimum memory must be less than or equal to maximum memory", "")
+ return v1alpha1.ClusterData{}
+ }
+ if !areResourcesValid(
+ autoscalerConfig.ApplicationController.ResourceMinimum.Cpu.ValueString(),
+ autoscalerConfig.ApplicationController.ResourceMaximum.Cpu.ValueString(),
+ ) {
+ diagnostics.AddError("application controller minimum CPU must be less than or equal to maximum CPU", "")
+ return v1alpha1.ClusterData{}
+ }
+ autoscalerConfigAPI.ApplicationController = &v1alpha1.AppControllerAutoScalingConfig{
+ ResourceMinimum: toResourcesAPIModel(autoscalerConfig.ApplicationController.ResourceMinimum),
+ ResourceMaximum: toResourcesAPIModel(autoscalerConfig.ApplicationController.ResourceMaximum),
+ }
+ }
+ }
return v1alpha1.ClusterData{
- Size: v1alpha1.ClusterSize(clusterData.Size.ValueString()),
+ Size: v1alpha1.ClusterSize(size),
AutoUpgradeDisabled: clusterData.AutoUpgradeDisabled.ValueBoolPointer(),
Kustomization: raw,
AppReplication: clusterData.AppReplication.ValueBoolPointer(),
@@ -310,6 +471,7 @@ func toClusterDataAPIModel(diagnostics *diag.Diagnostics, clusterData ClusterDat
EksAddonEnabled: clusterData.EksAddonEnabled.ValueBoolPointer(),
ManagedClusterConfig: managedConfig,
MultiClusterK8SDashboardEnabled: clusterData.MultiClusterK8SDashboardEnabled.ValueBoolPointer(),
+ AutoscalerConfig: autoscalerConfigAPI,
}
}
@@ -874,3 +1036,540 @@ func toManagedClusterConfigTFModel(cfg *argocdv1.ManagedClusterConfig) *ManagedC
SecretKey: types.StringValue(cfg.SecretKey),
}
}
+
+func toAutoScalerConfigTFModel(cfg *argocdv1.AutoScalerConfig) basetypes.ObjectValue {
+ attributeTypes := map[string]attr.Type{
+ "application_controller": basetypes.ObjectType{
+ AttrTypes: map[string]attr.Type{
+ "resource_minimum": basetypes.ObjectType{
+ AttrTypes: map[string]attr.Type{
+ "memory": types.StringType,
+ "cpu": types.StringType,
+ },
+ },
+ "resource_maximum": basetypes.ObjectType{
+ AttrTypes: map[string]attr.Type{
+ "memory": types.StringType,
+ "cpu": types.StringType,
+ },
+ },
+ },
+ },
+ "repo_server": basetypes.ObjectType{
+ AttrTypes: map[string]attr.Type{
+ "resource_minimum": basetypes.ObjectType{
+ AttrTypes: map[string]attr.Type{
+ "memory": types.StringType,
+ "cpu": types.StringType,
+ },
+ },
+ "resource_maximum": basetypes.ObjectType{
+ AttrTypes: map[string]attr.Type{
+ "memory": types.StringType,
+ "cpu": types.StringType,
+ },
+ },
+ "replicas_maximum": types.Int64Type,
+ "replicas_minimum": types.Int64Type,
+ },
+ },
+ }
+
+ attributes := map[string]attr.Value{}
+ if cfg.ApplicationController != nil {
+ attributes["application_controller"] = basetypes.NewObjectValueMust(
+ attributeTypes["application_controller"].(basetypes.ObjectType).AttrTypes,
+ map[string]attr.Value{
+ "resource_minimum": basetypes.NewObjectValueMust(
+ attributeTypes["application_controller"].(basetypes.ObjectType).AttrTypes["resource_minimum"].(basetypes.ObjectType).AttrTypes,
+ map[string]attr.Value{
+ "memory": basetypes.NewStringValue(cfg.ApplicationController.ResourceMinimum.Mem),
+ "cpu": basetypes.NewStringValue(cfg.ApplicationController.ResourceMinimum.Cpu),
+ },
+ ),
+ "resource_maximum": basetypes.NewObjectValueMust(
+ attributeTypes["application_controller"].(basetypes.ObjectType).AttrTypes["resource_maximum"].(basetypes.ObjectType).AttrTypes,
+ map[string]attr.Value{
+ "memory": basetypes.NewStringValue(cfg.ApplicationController.ResourceMaximum.Mem),
+ "cpu": basetypes.NewStringValue(cfg.ApplicationController.ResourceMaximum.Cpu),
+ },
+ ),
+ })
+ }
+ if cfg.RepoServer != nil {
+ attributes["repo_server"] = basetypes.NewObjectValueMust(
+ attributeTypes["repo_server"].(basetypes.ObjectType).AttrTypes,
+ map[string]attr.Value{
+ "resource_minimum": basetypes.NewObjectValueMust(
+ attributeTypes["repo_server"].(basetypes.ObjectType).AttrTypes["resource_minimum"].(basetypes.ObjectType).AttrTypes,
+ map[string]attr.Value{
+ "memory": basetypes.NewStringValue(cfg.RepoServer.ResourceMinimum.Mem),
+ "cpu": basetypes.NewStringValue(cfg.RepoServer.ResourceMinimum.Cpu),
+ },
+ ),
+ "resource_maximum": basetypes.NewObjectValueMust(
+ attributeTypes["repo_server"].(basetypes.ObjectType).AttrTypes["resource_maximum"].(basetypes.ObjectType).AttrTypes,
+ map[string]attr.Value{
+ "memory": basetypes.NewStringValue(cfg.RepoServer.ResourceMaximum.Mem),
+ "cpu": basetypes.NewStringValue(cfg.RepoServer.ResourceMaximum.Cpu),
+ },
+ ),
+ "replicas_maximum": basetypes.NewInt64Value(int64(cfg.RepoServer.ReplicaMaximum)),
+ "replicas_minimum": basetypes.NewInt64Value(int64(cfg.RepoServer.ReplicaMinimum)),
+ },
+ )
+ }
+
+ objectValue, diags := basetypes.NewObjectValue(attributeTypes, attributes)
+ if diags.HasError() {
+ return basetypes.NewObjectUnknown(attributeTypes)
+ }
+ return objectValue
+}
+
+func handleAgentSizeAndKustomization(diagnostics *diag.Diagnostics, clusterData *ClusterData, autoscalerConfig *AutoScalerConfig) (size string, kustomization runtime.RawExtension) {
+ // Validate configs
+ customSizeConfig := clusterData.CustomAgentSizeConfig
+ if autoscalerConfig != nil && clusterData.Size.ValueString() != "auto" {
+ diagnostics.AddError("autoscaler config should not be set when size is not auto", "")
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+ if customSizeConfig == nil && clusterData.Size.ValueString() == "custom" {
+ diagnostics.AddError("custom agent size config is required when size is custom", "")
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+ if customSizeConfig != nil && clusterData.Size.ValueString() != "custom" {
+ diagnostics.AddError("custom agent size config should not be set when size is not custom", "")
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+
+ // Parse existing kustomization if it exists
+ var existingConfig map[string]any
+ raw := runtime.RawExtension{}
+ if clusterData.Kustomization.ValueString() != "" {
+ if err := yaml.Unmarshal([]byte(clusterData.Kustomization.ValueString()), &raw); err != nil {
+ diagnostics.AddError("failed unmarshal kustomization string to yaml", err.Error())
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+ if err := yaml.Unmarshal(raw.Raw, &existingConfig); err != nil {
+ diagnostics.AddError("failed to parse existing kustomization", err.Error())
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+ }
+ if clusterData.Size.ValueString() != "custom" {
+ return clusterData.Size.ValueString(), raw
+ }
+
+ if existingConfig == nil {
+ existingConfig = map[string]any{
+ "apiVersion": "kustomize.config.k8s.io/v1beta1",
+ "kind": "Kustomization",
+ }
+ }
+ patches := make([]map[string]any, 0)
+ replicas := make([]map[string]any, 0)
+ if customSizeConfig.ApplicationController != nil {
+ if customSizeConfig.ApplicationController.Memory.ValueString() == "" || customSizeConfig.ApplicationController.Cpu.ValueString() == "" {
+ diagnostics.AddError("memory and cpu are required for app controller custom size", "")
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+ patches = append(patches, map[string]any{
+ "patch": generateAppControllerPatch(customSizeConfig.ApplicationController),
+ "target": map[string]string{
+ "kind": "Deployment",
+ "name": "argocd-application-controller",
+ },
+ })
+ }
+
+ if customSizeConfig.RepoServer != nil {
+ if customSizeConfig.RepoServer.Memory.ValueString() == "" || customSizeConfig.RepoServer.Cpu.ValueString() == "" || customSizeConfig.RepoServer.Replicas.ValueInt64() == 0 {
+ diagnostics.AddError("memory, cpu and replicas are required for repo server custom size", "")
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ } else if customSizeConfig.RepoServer.Replicas.ValueInt64() < 0 {
+ diagnostics.AddError("replicas must be greater than or equal to 0", "")
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+ patches = append(patches, map[string]any{
+ "patch": generateRepoServerPatch(customSizeConfig.RepoServer),
+ "target": map[string]string{
+ "kind": "Deployment",
+ "name": "argocd-repo-server",
+ },
+ })
+
+ replicas = append(replicas, map[string]any{
+ "count": customSizeConfig.RepoServer.Replicas.ValueInt64(),
+ "name": "argocd-repo-server",
+ })
+ }
+
+ if existingPatches, ok := existingConfig["patches"].([]any); ok {
+ patches = append(filterNonSizePatches(existingPatches), patches...)
+ }
+ if existingReplicas, ok := existingConfig["replicas"].([]any); ok {
+ replicas = append(filterNonRepoServerReplicas(existingReplicas), replicas...)
+ }
+
+ existingConfig["patches"] = patches
+ if len(replicas) > 0 {
+ existingConfig["replicas"] = replicas
+ }
+
+ yamlData, err := yaml.Marshal(existingConfig)
+ if err != nil {
+ diagnostics.AddError("failed to marshal config to yaml", err.Error())
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+
+ if err = yaml.Unmarshal(yamlData, &raw); err != nil {
+ diagnostics.AddError("failed unmarshal kustomization string to yaml", err.Error())
+ return clusterData.Size.ValueString(), runtime.RawExtension{}
+ }
+
+ // Custom size will be represented as large with kustomization
+ return "large", raw
+}
+
+func filterNonSizePatches(patches []any) []map[string]any {
+ var filtered []map[string]any
+ for _, p := range patches {
+ patch, ok := p.(map[string]any)
+ if !ok {
+ continue
+ }
+ target, ok := patch["target"].(map[string]any)
+ if !ok {
+ filtered = append(filtered, patch)
+ continue
+ }
+ name, ok := target["name"].(string)
+ if !ok || (name != "argocd-application-controller" && name != "argocd-repo-server") {
+ filtered = append(filtered, patch)
+ }
+ }
+ return filtered
+}
+
+func filterNonRepoServerReplicas(replicas []any) []map[string]any {
+ var filtered []map[string]any
+ for _, r := range replicas {
+ replica, ok := r.(map[string]any)
+ if !ok {
+ continue
+ }
+ name, ok := replica["name"].(string)
+ if !ok || name != "argocd-repo-server" {
+ filtered = append(filtered, replica)
+ }
+ }
+ return filtered
+}
+
+func filterNonSizePatchesKustomize(patches []kustomizetypes.Patch) []kustomizetypes.Patch {
+ var filtered []kustomizetypes.Patch
+ for _, p := range patches {
+ if p.Target == nil || (p.Target.Name != "argocd-application-controller" && p.Target.Name != "argocd-repo-server") {
+ filtered = append(filtered, p)
+ }
+ }
+ return filtered
+}
+
+func filterNonRepoServerReplicasKustomize(replicas []kustomizetypes.Replica) []kustomizetypes.Replica {
+ var filtered []kustomizetypes.Replica
+ for _, r := range replicas {
+ if r.Name != "argocd-repo-server" {
+ filtered = append(filtered, r)
+ }
+ }
+ return filtered
+}
+
+func generateAppControllerPatch(config *AppControllerCustomAgentSizeConfig) string {
+ if config == nil {
+ return ""
+ }
+ return fmt.Sprintf(`apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: argocd-application-controller
+spec:
+ template:
+ spec:
+ containers:
+ - name: argocd-application-controller
+ resources:
+ limits:
+ memory: %s
+ requests:
+ cpu: %s
+ memory: %s`,
+ config.Memory.ValueString(),
+ config.Cpu.ValueString(),
+ config.Memory.ValueString())
+}
+
+func generateRepoServerPatch(config *RepoServerCustomAgentSizeConfig) string {
+ if config == nil {
+ return ""
+ }
+ return fmt.Sprintf(`apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: argocd-repo-server
+spec:
+ template:
+ spec:
+ containers:
+ - name: argocd-repo-server
+ resources:
+ limits:
+ memory: %s
+ requests:
+ cpu: %s
+ memory: %s`,
+ config.Memory.ValueString(),
+ config.Cpu.ValueString(),
+ config.Memory.ValueString())
+}
+
+func toResourcesAPIModel(resources *Resources) *v1alpha1.Resources {
+ if resources == nil {
+ return nil
+ }
+ return &v1alpha1.Resources{
+ Mem: resources.Memory.ValueString(),
+ Cpu: resources.Cpu.ValueString(),
+ }
+}
+
+func extractCustomSizeConfig(existingConfig kustomizetypes.Kustomization) *CustomAgentSizeConfig {
+ var appController *AppControllerCustomAgentSizeConfig
+ var repoServer *RepoServerCustomAgentSizeConfig
+
+ for _, p := range existingConfig.Patches {
+ var patch appsv1.Deployment
+ if err := yaml.Unmarshal([]byte(p.Patch), &patch); err != nil {
+ continue
+ }
+
+ switch p.Target.Name {
+ case "argocd-application-controller":
+ for _, container := range patch.Spec.Template.Spec.Containers {
+ if container.Name == "argocd-application-controller" {
+ appController = &AppControllerCustomAgentSizeConfig{
+ Memory: tftypes.StringValue(container.Resources.Requests.Memory().String()),
+ Cpu: tftypes.StringValue(container.Resources.Requests.Cpu().String()),
+ }
+ break
+ }
+ }
+ case "argocd-repo-server":
+ for _, container := range patch.Spec.Template.Spec.Containers {
+ if container.Name == "argocd-repo-server" {
+ repoServer = &RepoServerCustomAgentSizeConfig{
+ Memory: tftypes.StringValue(container.Resources.Requests.Memory().String()),
+ Cpu: tftypes.StringValue(container.Resources.Requests.Cpu().String()),
+ }
+ break
+ }
+ }
+ }
+ }
+ if repoServer != nil {
+ for _, r := range existingConfig.Replicas {
+ if r.Name == "argocd-repo-server" {
+ repoServer.Replicas = tftypes.Int64Value(r.Count)
+ break
+ }
+ }
+ }
+
+ if appController == nil && repoServer == nil {
+ return nil
+ }
+
+ return &CustomAgentSizeConfig{
+ ApplicationController: appController,
+ RepoServer: repoServer,
+ }
+}
+
+func areCustomAgentConfigsEquivalent(config1, config2 *CustomAgentSizeConfig) bool {
+ if config1 == nil || config2 == nil {
+ return config1 == config2
+ }
+ if config1.ApplicationController != nil && config2.ApplicationController != nil {
+ if !areResourcesEquivalent(
+ config1.ApplicationController.Cpu.ValueString(),
+ config2.ApplicationController.Cpu.ValueString(),
+ ) || !areResourcesEquivalent(
+ config1.ApplicationController.Memory.ValueString(),
+ config2.ApplicationController.Memory.ValueString(),
+ ) {
+ return false
+ }
+ } else if config1.ApplicationController != nil || config2.ApplicationController != nil {
+ return false
+ }
+ if config1.RepoServer != nil && config2.RepoServer != nil {
+ if !areResourcesEquivalent(
+ config1.RepoServer.Cpu.ValueString(),
+ config2.RepoServer.Cpu.ValueString(),
+ ) || !areResourcesEquivalent(
+ config1.RepoServer.Memory.ValueString(),
+ config2.RepoServer.Memory.ValueString(),
+ ) || config1.RepoServer.Replicas != config2.RepoServer.Replicas {
+ return false
+ }
+ } else if config1.RepoServer != nil || config2.RepoServer != nil {
+ return false
+ }
+ return true
+}
+
+func areAutoScalerConfigsEquivalent(plan, now *AutoScalerConfig) bool {
+ if plan == nil {
+ return true
+ }
+ if plan.ApplicationController != nil && now.ApplicationController != nil {
+ if !areResourcesEquivalent(
+ plan.ApplicationController.ResourceMinimum.Cpu.ValueString(),
+ now.ApplicationController.ResourceMinimum.Cpu.ValueString(),
+ ) || !areResourcesEquivalent(
+ plan.ApplicationController.ResourceMinimum.Memory.ValueString(),
+ now.ApplicationController.ResourceMinimum.Memory.ValueString(),
+ ) || !areResourcesEquivalent(
+ plan.ApplicationController.ResourceMaximum.Cpu.ValueString(),
+ now.ApplicationController.ResourceMaximum.Cpu.ValueString(),
+ ) || !areResourcesEquivalent(
+ plan.ApplicationController.ResourceMaximum.Memory.ValueString(),
+ now.ApplicationController.ResourceMaximum.Memory.ValueString(),
+ ) {
+ return false
+ }
+ }
+ if plan.RepoServer != nil && now.RepoServer != nil {
+ if !areResourcesEquivalent(
+ plan.RepoServer.ResourceMinimum.Cpu.ValueString(),
+ now.RepoServer.ResourceMinimum.Cpu.ValueString(),
+ ) || !areResourcesEquivalent(
+ plan.RepoServer.ResourceMinimum.Memory.ValueString(),
+ now.RepoServer.ResourceMinimum.Memory.ValueString(),
+ ) || !areResourcesEquivalent(
+ plan.RepoServer.ResourceMaximum.Cpu.ValueString(),
+ now.RepoServer.ResourceMaximum.Cpu.ValueString(),
+ ) || !areResourcesEquivalent(
+ plan.RepoServer.ResourceMaximum.Memory.ValueString(),
+ now.RepoServer.ResourceMaximum.Memory.ValueString(),
+ ) || plan.RepoServer.ReplicasMaximum != now.RepoServer.ReplicasMaximum ||
+ plan.RepoServer.ReplicasMinimum != now.RepoServer.ReplicasMinimum {
+ return false
+ }
+ }
+ return true
+}
+
+func areResourcesEquivalent(plan, new string) bool {
+ if plan == "" {
+ return true
+ }
+ planQ, err1 := resource.ParseQuantity(plan)
+ newQ, err2 := resource.ParseQuantity(new)
+ if err1 != nil || err2 != nil {
+ return plan == new
+ }
+
+ planVal := planQ.Value()
+ newVal := newQ.Value()
+
+ var diff float64
+ if planVal > newVal {
+ diff = float64(planVal-newVal) / float64(planVal)
+ } else {
+ diff = float64(newVal-planVal) / float64(newVal)
+ }
+
+ // there maybe Mi to Gi conversion with some rounding difference
+ return diff <= 0.05
+}
+
+func extractConfigFromObjectValue(obj basetypes.ObjectValue) *AutoScalerConfig {
+ if obj.IsNull() || obj.IsUnknown() {
+ return nil
+ }
+
+ attrs := obj.Attributes()
+ config := &AutoScalerConfig{}
+ if appCtrl, ok := attrs["application_controller"].(basetypes.ObjectValue); ok {
+ appCtrlAttrs := appCtrl.Attributes()
+ if resMin, ok := appCtrlAttrs["resource_minimum"].(basetypes.ObjectValue); ok {
+ resMinAttrs := resMin.Attributes()
+ if cpu, ok := resMinAttrs["cpu"].(basetypes.StringValue); ok {
+ if mem, ok := resMinAttrs["memory"].(basetypes.StringValue); ok {
+ if resMax, ok := appCtrlAttrs["resource_maximum"].(basetypes.ObjectValue); ok {
+ resMaxAttrs := resMax.Attributes()
+ if maxCpu, ok := resMaxAttrs["cpu"].(basetypes.StringValue); ok {
+ if maxMem, ok := resMaxAttrs["memory"].(basetypes.StringValue); ok {
+ config.ApplicationController = &AppControllerAutoScalingConfig{
+ ResourceMinimum: &Resources{
+ Cpu: cpu,
+ Memory: mem,
+ },
+ ResourceMaximum: &Resources{
+ Cpu: maxCpu,
+ Memory: maxMem,
+ },
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if repoServer, ok := attrs["repo_server"].(basetypes.ObjectValue); ok {
+ repoServerAttrs := repoServer.Attributes()
+ if resMin, ok := repoServerAttrs["resource_minimum"].(basetypes.ObjectValue); ok {
+ resMinAttrs := resMin.Attributes()
+ if cpu, ok := resMinAttrs["cpu"].(basetypes.StringValue); ok {
+ if mem, ok := resMinAttrs["memory"].(basetypes.StringValue); ok {
+ if resMax, ok := repoServerAttrs["resource_maximum"].(basetypes.ObjectValue); ok {
+ resMaxAttrs := resMax.Attributes()
+ if maxCpu, ok := resMaxAttrs["cpu"].(basetypes.StringValue); ok {
+ if maxMem, ok := resMaxAttrs["memory"].(basetypes.StringValue); ok {
+ if replMax, ok := repoServerAttrs["replicas_maximum"].(basetypes.Int64Value); ok {
+ if replMin, ok := repoServerAttrs["replicas_minimum"].(basetypes.Int64Value); ok {
+ config.RepoServer = &RepoServerAutoScalingConfig{
+ ResourceMinimum: &Resources{
+ Cpu: cpu,
+ Memory: mem,
+ },
+ ResourceMaximum: &Resources{
+ Cpu: maxCpu,
+ Memory: maxMem,
+ },
+ ReplicasMaximum: replMax,
+ ReplicasMinimum: replMin,
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return config
+}
+
+func areResourcesValid(min, max string) bool {
+ minQ, err1 := resource.ParseQuantity(min)
+ maxQ, err2 := resource.ParseQuantity(max)
+ if err1 != nil || err2 != nil {
+ return true
+ }
+ return minQ.Cmp(maxQ) <= 0
+}
diff --git a/docs/data-sources/cluster.md b/docs/data-sources/cluster.md
index c59fa2d..c6fb930 100644
--- a/docs/data-sources/cluster.md
+++ b/docs/data-sources/cluster.md
@@ -77,16 +77,111 @@ Read-Only:
Read-Only:
- `app_replication` (Boolean) Enables Argo CD state replication to the managed cluster that allows disconnecting the cluster from Akuity Platform without losing core Argocd features
+- `auto_agent_size_config` (Attributes) Autoscaler config for auto agent size (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config))
- `auto_upgrade_disabled` (Boolean) Disables agents auto upgrade. On resource update terraform will try to update the agent if this is set to `true`. Otherwise agent will update itself automatically
+- `custom_agent_size_config` (Attributes) Custom agent size config (see [below for nested schema](#nestedatt--spec--data--custom_agent_size_config))
- `datadog_annotations_enabled` (Boolean) Enable Datadog metrics collection of Application Controller and Repo Server. Make sure that you install Datadog agent in cluster.
- `eks_addon_enabled` (Boolean) Enable this if you are installing this cluster on EKS.
- `kustomization` (String) Kustomize configuration that will be applied to generated agent installation manifests
- `managed_cluster_config` (Attributes) The config to access managed Kubernetes cluster. By default agent is using "in-cluster" config. (see [below for nested schema](#nestedatt--spec--data--managed_cluster_config))
- `multi_cluster_k8s_dashboard_enabled` (Boolean) Enable the KubeVision feature on the managed cluster
- `redis_tunneling` (Boolean) Enables the ability to connect to Redis over a web-socket tunnel that allows using Akuity agent behind HTTPS proxy
-- `size` (String) Cluster Size. One of `small`, `medium` or `large`
+- `size` (String) Cluster Size. One of `small`, `medium`, `large`, `custom` or `auto`
- `target_version` (String) The version of the agent to install on your cluster
+
+### Nested Schema for `spec.data.auto_agent_size_config`
+
+Read-Only:
+
+- `application_controller` (Attributes) Application Controller auto scaling config (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--application_controller))
+- `repo_server` (Attributes) Repo Server auto scaling config (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--repo_server))
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.application_controller`
+
+Read-Only:
+
+- `resource_maximum` (Attributes) Resource maximum (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--application_controller--resource_maximum))
+- `resource_minimum` (Attributes) Resource minimum (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--application_controller--resource_minimum))
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.application_controller.resource_maximum`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.application_controller.resource_minimum`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.repo_server`
+
+Read-Only:
+
+- `replicas_maximum` (Number) Replica maximum
+- `replicas_minimum` (Number) Replica minimum
+- `resource_maximum` (Attributes) Resource maximum (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--repo_server--resource_maximum))
+- `resource_minimum` (Attributes) Resource minimum (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--repo_server--resource_minimum))
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.repo_server.resource_maximum`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.repo_server.resource_minimum`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+
+
+### Nested Schema for `spec.data.custom_agent_size_config`
+
+Read-Only:
+
+- `application_controller` (Attributes) Application Controller custom agent size config (see [below for nested schema](#nestedatt--spec--data--custom_agent_size_config--application_controller))
+- `repo_server` (Attributes) Repo Server custom agent size config (see [below for nested schema](#nestedatt--spec--data--custom_agent_size_config--repo_server))
+
+
+### Nested Schema for `spec.data.custom_agent_size_config.application_controller`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `spec.data.custom_agent_size_config.repo_server`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+- `replicas` (Number) Replica
+
+
+
### Nested Schema for `spec.data.managed_cluster_config`
diff --git a/docs/data-sources/clusters.md b/docs/data-sources/clusters.md
index aa010a1..b3f7236 100644
--- a/docs/data-sources/clusters.md
+++ b/docs/data-sources/clusters.md
@@ -88,16 +88,111 @@ Read-Only:
Read-Only:
- `app_replication` (Boolean) Enables Argo CD state replication to the managed cluster that allows disconnecting the cluster from Akuity Platform without losing core Argocd features
+- `auto_agent_size_config` (Attributes) Autoscaler config for auto agent size (see [below for nested schema](#nestedatt--clusters--spec--data--auto_agent_size_config))
- `auto_upgrade_disabled` (Boolean) Disables agents auto upgrade. On resource update terraform will try to update the agent if this is set to `true`. Otherwise agent will update itself automatically
+- `custom_agent_size_config` (Attributes) Custom agent size config (see [below for nested schema](#nestedatt--clusters--spec--data--custom_agent_size_config))
- `datadog_annotations_enabled` (Boolean) Enable Datadog metrics collection of Application Controller and Repo Server. Make sure that you install Datadog agent in cluster.
- `eks_addon_enabled` (Boolean) Enable this if you are installing this cluster on EKS.
- `kustomization` (String) Kustomize configuration that will be applied to generated agent installation manifests
- `managed_cluster_config` (Attributes) The config to access managed Kubernetes cluster. By default agent is using "in-cluster" config. (see [below for nested schema](#nestedatt--clusters--spec--data--managed_cluster_config))
- `multi_cluster_k8s_dashboard_enabled` (Boolean) Enable the KubeVision feature on the managed cluster
- `redis_tunneling` (Boolean) Enables the ability to connect to Redis over a web-socket tunnel that allows using Akuity agent behind HTTPS proxy
-- `size` (String) Cluster Size. One of `small`, `medium` or `large`
+- `size` (String) Cluster Size. One of `small`, `medium`, `large`, `custom` or `auto`
- `target_version` (String) The version of the agent to install on your cluster
+
+### Nested Schema for `clusters.spec.data.auto_agent_size_config`
+
+Read-Only:
+
+- `application_controller` (Attributes) Application Controller auto scaling config (see [below for nested schema](#nestedatt--clusters--spec--data--auto_agent_size_config--application_controller))
+- `repo_server` (Attributes) Repo Server auto scaling config (see [below for nested schema](#nestedatt--clusters--spec--data--auto_agent_size_config--repo_server))
+
+
+### Nested Schema for `clusters.spec.data.auto_agent_size_config.application_controller`
+
+Read-Only:
+
+- `resource_maximum` (Attributes) Resource maximum (see [below for nested schema](#nestedatt--clusters--spec--data--auto_agent_size_config--application_controller--resource_maximum))
+- `resource_minimum` (Attributes) Resource minimum (see [below for nested schema](#nestedatt--clusters--spec--data--auto_agent_size_config--application_controller--resource_minimum))
+
+
+### Nested Schema for `clusters.spec.data.auto_agent_size_config.application_controller.resource_maximum`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `clusters.spec.data.auto_agent_size_config.application_controller.resource_minimum`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+
+### Nested Schema for `clusters.spec.data.auto_agent_size_config.repo_server`
+
+Read-Only:
+
+- `replicas_maximum` (Number) Replica maximum
+- `replicas_minimum` (Number) Replica minimum
+- `resource_maximum` (Attributes) Resource maximum (see [below for nested schema](#nestedatt--clusters--spec--data--auto_agent_size_config--repo_server--resource_maximum))
+- `resource_minimum` (Attributes) Resource minimum (see [below for nested schema](#nestedatt--clusters--spec--data--auto_agent_size_config--repo_server--resource_minimum))
+
+
+### Nested Schema for `clusters.spec.data.auto_agent_size_config.repo_server.resource_maximum`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `clusters.spec.data.auto_agent_size_config.repo_server.resource_minimum`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+
+
+### Nested Schema for `clusters.spec.data.custom_agent_size_config`
+
+Read-Only:
+
+- `application_controller` (Attributes) Application Controller custom agent size config (see [below for nested schema](#nestedatt--clusters--spec--data--custom_agent_size_config--application_controller))
+- `repo_server` (Attributes) Repo Server custom agent size config (see [below for nested schema](#nestedatt--clusters--spec--data--custom_agent_size_config--repo_server))
+
+
+### Nested Schema for `clusters.spec.data.custom_agent_size_config.application_controller`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `clusters.spec.data.custom_agent_size_config.repo_server`
+
+Read-Only:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+- `replicas` (Number) Replica
+
+
+
### Nested Schema for `clusters.spec.data.managed_cluster_config`
diff --git a/docs/resources/cluster.md b/docs/resources/cluster.md
index 04ee793..6208de8 100644
--- a/docs/resources/cluster.md
+++ b/docs/resources/cluster.md
@@ -36,6 +36,99 @@ resource "akp_cluster" "my-cluster" {
For a complete working example using a GKE cluster, see [akuity/examples](https://github.com/akuity/examples/tree/main/terraform/akuity).
+## Example Usage (Custom agent size)
+```terraform
+data "akp_instance" "example" {
+ name = "test"
+}
+
+resource "akp_cluster" "example" {
+ instance_id = data.akp_instance.example.id
+ name = "test-cluster"
+ namespace = "test"
+ labels = {
+ test-label = true
+ }
+ annotations = {
+ test-annotation = false
+ }
+ spec = {
+ namespace_scoped = true
+ description = "test-description"
+ data = {
+ size = "custom"
+ auto_upgrade_disabled = false
+ custom_agent_size_config = {
+ application_controller = {
+ cpu = "1000m"
+ memory = "2Gi"
+ }
+ repo_server = {
+ replicas = 3,
+ cpu = "1000m"
+ memory = "2Gi"
+ }
+ }
+ }
+ }
+}
+```
+
+## Example Usage (Auto agent size)
+```terraform
+data "akp_instance" "example" {
+ name = "test"
+}
+
+resource "akp_cluster" "example" {
+ instance_id = data.akp_instance.example.id
+ name = "test-cluster"
+ namespace = "test"
+ labels = {
+ test-label = true
+ }
+ annotations = {
+ test-annotation = false
+ }
+ spec = {
+ namespace_scoped = true
+ description = "test-description"
+ data = {
+ size = "auto"
+ # auto_upgrade_disabled can be set to true if you want to enable auto scaling of the agent size for the cluster
+ auto_upgrade_disabled = false
+ auto_agent_size_config = {
+ application_controller = {
+ resource_maximum = {
+ cpu = "3"
+ memory = "2Gi"
+ },
+ resource_minimum = {
+ cpu = "250m",
+ memory = "1Gi"
+ }
+ },
+ repo_server = {
+ replicas_maximum = 3,
+ # minimum number of replicas should be set to 1
+ replicas_minimum = 1,
+ resource_maximum = {
+ cpu = "3"
+ memory = "2.00Gi"
+ },
+ resource_minimum = {
+ cpu = "250m",
+ memory = "256Mi"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+- This example uses the `auto` agent size, which will automatically scale the agent based on the number of applications in the cluster. `auto_upgrade_disabled` cannot be set to `true` when using `auto` agent size.
+
## Example Usage (Exhaustive)
```terraform
data "akp_instance" "example" {
@@ -147,12 +240,14 @@ Optional:
Required:
-- `size` (String) Cluster Size. One of `small`, `medium` or `large`
+- `size` (String) Cluster Size. One of `small`, `medium`, `large`, `custom` or `auto`
Optional:
- `app_replication` (Boolean) Enables Argo CD state replication to the managed cluster that allows disconnecting the cluster from Akuity Platform without losing core Argocd features
+- `auto_agent_size_config` (Attributes) Autoscaler config for auto agent size (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config))
- `auto_upgrade_disabled` (Boolean) Disable Agents Auto Upgrade. On resource update terraform will try to update the agent if this is set to `true`. Otherwise agent will update itself automatically
+- `custom_agent_size_config` (Attributes) Custom agent size config (see [below for nested schema](#nestedatt--spec--data--custom_agent_size_config))
- `datadog_annotations_enabled` (Boolean) Enable Datadog metrics collection of Application Controller and Repo Server. Make sure that you install Datadog agent in cluster.
- `eks_addon_enabled` (Boolean) Enable this if you are installing this cluster on EKS.
- `kustomization` (String) Kustomize configuration that will be applied to generated agent installation manifests
@@ -161,6 +256,99 @@ Optional:
- `redis_tunneling` (Boolean) Enables the ability to connect to Redis over a web-socket tunnel that allows using Akuity agent behind HTTPS proxy
- `target_version` (String) The version of the agent to install on your cluster
+
+### Nested Schema for `spec.data.auto_agent_size_config`
+
+Optional:
+
+- `application_controller` (Attributes) Application Controller auto scaling config (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--application_controller))
+- `repo_server` (Attributes) Repo Server auto scaling config (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--repo_server))
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.application_controller`
+
+Optional:
+
+- `resource_maximum` (Attributes) Resource maximum (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--application_controller--resource_maximum))
+- `resource_minimum` (Attributes) Resource minimum (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--application_controller--resource_minimum))
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.application_controller.resource_maximum`
+
+Optional:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.application_controller.resource_minimum`
+
+Optional:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.repo_server`
+
+Optional:
+
+- `replicas_maximum` (Number) Replica maximum
+- `replicas_minimum` (Number) Replica minimum, this should be set to 1 as a minimum
+- `resource_maximum` (Attributes) Resource maximum (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--repo_server--resource_maximum))
+- `resource_minimum` (Attributes) Resource minimum (see [below for nested schema](#nestedatt--spec--data--auto_agent_size_config--repo_server--resource_minimum))
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.repo_server.resource_maximum`
+
+Optional:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `spec.data.auto_agent_size_config.repo_server.resource_minimum`
+
+Optional:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+
+
+### Nested Schema for `spec.data.custom_agent_size_config`
+
+Optional:
+
+- `application_controller` (Attributes) Application Controller custom agent size config (see [below for nested schema](#nestedatt--spec--data--custom_agent_size_config--application_controller))
+- `repo_server` (Attributes) Repo Server custom agent size config (see [below for nested schema](#nestedatt--spec--data--custom_agent_size_config--repo_server))
+
+
+### Nested Schema for `spec.data.custom_agent_size_config.application_controller`
+
+Optional:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+
+
+
+### Nested Schema for `spec.data.custom_agent_size_config.repo_server`
+
+Optional:
+
+- `cpu` (String) CPU
+- `memory` (String) Memory
+- `replicas` (Number) Replica
+
+
+
### Nested Schema for `spec.data.managed_cluster_config`
diff --git a/examples/resources/akp_cluster/auto_agent_size.tf b/examples/resources/akp_cluster/auto_agent_size.tf
new file mode 100644
index 0000000..f2ebd84
--- /dev/null
+++ b/examples/resources/akp_cluster/auto_agent_size.tf
@@ -0,0 +1,49 @@
+data "akp_instance" "example" {
+ name = "test"
+}
+
+resource "akp_cluster" "example" {
+ instance_id = data.akp_instance.example.id
+ name = "test-cluster"
+ namespace = "test"
+ labels = {
+ test-label = true
+ }
+ annotations = {
+ test-annotation = false
+ }
+ spec = {
+ namespace_scoped = true
+ description = "test-description"
+ data = {
+ size = "auto"
+ # auto_upgrade_disabled can be set to true if you want to enable auto scaling of the agent size for the cluster
+ auto_upgrade_disabled = false
+ auto_agent_size_config = {
+ application_controller = {
+ resource_maximum = {
+ cpu = "3"
+ memory = "2Gi"
+ },
+ resource_minimum = {
+ cpu = "250m",
+ memory = "1Gi"
+ }
+ },
+ repo_server = {
+ replicas_maximum = 3,
+ # minimum number of replicas should be set to 1
+ replicas_minimum = 1,
+ resource_maximum = {
+ cpu = "3"
+ memory = "2.00Gi"
+ },
+ resource_minimum = {
+ cpu = "250m",
+ memory = "256Mi"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/resources/akp_cluster/custom_agent_size.tf b/examples/resources/akp_cluster/custom_agent_size.tf
new file mode 100644
index 0000000..ba2bd8f
--- /dev/null
+++ b/examples/resources/akp_cluster/custom_agent_size.tf
@@ -0,0 +1,34 @@
+data "akp_instance" "example" {
+ name = "test"
+}
+
+resource "akp_cluster" "example" {
+ instance_id = data.akp_instance.example.id
+ name = "test-cluster"
+ namespace = "test"
+ labels = {
+ test-label = true
+ }
+ annotations = {
+ test-annotation = false
+ }
+ spec = {
+ namespace_scoped = true
+ description = "test-description"
+ data = {
+ size = "custom"
+ auto_upgrade_disabled = false
+ custom_agent_size_config = {
+ application_controller = {
+ cpu = "1000m"
+ memory = "2Gi"
+ }
+ repo_server = {
+ replicas = 3,
+ cpu = "1000m"
+ memory = "2Gi"
+ }
+ }
+ }
+ }
+}
diff --git a/templates/resources/cluster.md.tmpl b/templates/resources/cluster.md.tmpl
index ea48fa4..55a6eb6 100644
--- a/templates/resources/cluster.md.tmpl
+++ b/templates/resources/cluster.md.tmpl
@@ -19,6 +19,14 @@ description: |-
For a complete working example using a GKE cluster, see [akuity/examples](https://github.com/akuity/examples/tree/main/terraform/akuity).
+## Example Usage (Custom agent size)
+{{ tffile "./examples/resources/akp_cluster/custom_agent_size.tf" }}
+
+## Example Usage (Auto agent size)
+{{ tffile "./examples/resources/akp_cluster/auto_agent_size.tf" }}
+
+- This example uses the `auto` agent size, which will automatically scale the agent based on the number of applications in the cluster. `auto_upgrade_disabled` cannot be set to `true` when using `auto` agent size.
+
## Example Usage (Exhaustive)
{{ tffile "./examples/resources/akp_cluster/resource.tf" }}
{{- end }}