diff --git a/.changelog/634.txt b/.changelog/634.txt
new file mode 100644
index 000000000..b7ba10bbd
--- /dev/null
+++ b/.changelog/634.txt
@@ -0,0 +1,5 @@
+```release-note:new-resource
+ - Support for AutoStopping Rules - AWS VM, Azure VM, GCP VM, AWS RDS, AWS ECS
+ - This version does not support dry run AutoStopping rule creation, provision for hide progress page and tag based ECS rule creation
+ - Does not have support for schedules feature
+```
\ No newline at end of file
diff --git a/docs/data-sources/autostopping_rule_ecs.md b/docs/data-sources/autostopping_rule_ecs.md
new file mode 100644
index 000000000..badbbdc43
--- /dev/null
+++ b/docs/data-sources/autostopping_rule_ecs.md
@@ -0,0 +1,73 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "harness_autostopping_rule_ecs Data Source - terraform-provider-harness"
+subcategory: "Next Gen"
+description: |-
+ Data source for retrieving a Harness Variable.
+---
+
+# harness_autostopping_rule_ecs (Data Source)
+
+Data source for retrieving a Harness Variable.
+
+## Example Usage
+
+```terraform
+data "harness_autostopping_rule_ecs" "example" {
+ identifier = "identifier"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `cloud_connector_id` (String) Id of the cloud connector
+- `name` (String) Name of the rule
+
+### Optional
+
+- `container` (Block List, Max: 1) (see [below for nested schema](#nestedblock--container))
+- `custom_domains` (List of String) Custom URLs used to access the instances
+- `depends` (Block List) Dependent rules (see [below for nested schema](#nestedblock--depends))
+- `http` (Block List) Http routing configuration (see [below for nested schema](#nestedblock--http))
+- `idle_time_mins` (Number) Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+- `identifier` (Number) Unique identifier of the resource
+
+
+### Nested Schema for `container`
+
+Required:
+
+- `cluster` (String) Name of cluster in which service belong to
+- `region` (String) Region of cluster
+- `service` (String) Name of service to be onboarded
+
+Optional:
+
+- `task_count` (Number) Desired number of tasks on warming up a rule
+
+
+
+### Nested Schema for `depends`
+
+Required:
+
+- `rule_id` (Number) Rule id of the dependent rule
+
+Optional:
+
+- `delay_in_sec` (Number) Number of seconds the rule should wait after warming up the dependent rule
+
+
+
+### Nested Schema for `http`
+
+Required:
+
+- `proxy_id` (String) Id of the proxy
diff --git a/docs/data-sources/autostopping_rule_rds.md b/docs/data-sources/autostopping_rule_rds.md
new file mode 100644
index 000000000..ad4d29b3c
--- /dev/null
+++ b/docs/data-sources/autostopping_rule_rds.md
@@ -0,0 +1,82 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "harness_autostopping_rule_rds Data Source - terraform-provider-harness"
+subcategory: "Next Gen"
+description: |-
+ Data source for retrieving a Harness Variable.
+---
+
+# harness_autostopping_rule_rds (Data Source)
+
+Data source for retrieving a Harness Variable.
+
+## Example Usage
+
+```terraform
+data "harness_autostopping_rule_rds" "example" {
+ identifier = "identifier"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `cloud_connector_id` (String) Id of the cloud connector
+- `database` (Block List, Min: 1, Max: 1) (see [below for nested schema](#nestedblock--database))
+- `name` (String) Name of the rule
+
+### Optional
+
+- `depends` (Block List) Dependent rules (see [below for nested schema](#nestedblock--depends))
+- `idle_time_mins` (Number) Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.
+- `tcp` (Block List) TCP routing configuration (see [below for nested schema](#nestedblock--tcp))
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+- `identifier` (Number) Unique identifier of the resource
+
+
+### Nested Schema for `database`
+
+Required:
+
+- `id` (String) ID of the database
+- `region` (String) Region to which database belong to
+
+
+
+### Nested Schema for `depends`
+
+Required:
+
+- `rule_id` (Number) Rule id of the dependent rule
+
+Optional:
+
+- `delay_in_sec` (Number) Number of seconds the rule should wait after warming up the dependent rule
+
+
+
+### Nested Schema for `tcp`
+
+Required:
+
+- `proxy_id` (String) Id of the Proxy
+
+Optional:
+
+- `forward_rule` (Block List) Additional tcp forwarding rules (see [below for nested schema](#nestedblock--tcp--forward_rule))
+
+
+### Nested Schema for `tcp.forward_rule`
+
+Required:
+
+- `port` (Number) Port to listen on the vm
+
+Optional:
+
+- `connect_on` (Number) Port to listen on the proxy
diff --git a/docs/data-sources/autostopping_rule_vm.md b/docs/data-sources/autostopping_rule_vm.md
new file mode 100644
index 000000000..5793b0298
--- /dev/null
+++ b/docs/data-sources/autostopping_rule_vm.md
@@ -0,0 +1,163 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "harness_autostopping_rule_vm Data Source - terraform-provider-harness"
+subcategory: "Next Gen"
+description: |-
+ Data source for retrieving a Harness Variable.
+---
+
+# harness_autostopping_rule_vm (Data Source)
+
+Data source for retrieving a Harness Variable.
+
+## Example Usage
+
+```terraform
+data "harness_autostopping_rule_vm" "example" {
+ identifier = "identifier"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `cloud_connector_id` (String) Id of the cloud connector
+- `filter` (Block List, Min: 1, Max: 1) (see [below for nested schema](#nestedblock--filter))
+- `name` (String) Name of the rule
+
+### Optional
+
+- `custom_domains` (List of String) Custom URLs used to access the instances
+- `depends` (Block List) Dependent rules (see [below for nested schema](#nestedblock--depends))
+- `http` (Block List) Http routing configuration (see [below for nested schema](#nestedblock--http))
+- `idle_time_mins` (Number) Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.
+- `tcp` (Block List) TCP routing configuration (see [below for nested schema](#nestedblock--tcp))
+- `use_spot` (Boolean) Boolean that indicates whether the selected instances should be converted to spot vm
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+- `identifier` (Number) Unique identifier of the resource
+
+
+### Nested Schema for `filter`
+
+Required:
+
+- `vm_ids` (List of String) Ids of instances that needs to be managed using the AutoStopping rules
+
+Optional:
+
+- `regions` (List of String) Regions of instances that needs to be managed using the AutoStopping rules
+- `tags` (Block List) Tags of instances that needs to be managed using the AutoStopping rules (see [below for nested schema](#nestedblock--filter--tags))
+- `zones` (List of String) Zones of instances that needs to be managed using the AutoStopping rules
+
+
+### Nested Schema for `filter.tags`
+
+Required:
+
+- `key` (String)
+- `value` (String)
+
+
+
+
+### Nested Schema for `depends`
+
+Required:
+
+- `rule_id` (Number) Rule id of the dependent rule
+
+Optional:
+
+- `delay_in_sec` (Number) Number of seconds the rule should wait after warming up the dependent rule
+
+
+
+### Nested Schema for `http`
+
+Required:
+
+- `proxy_id` (String) Id of the proxy
+
+Optional:
+
+- `health` (Block List) Health Check Details (see [below for nested schema](#nestedblock--http--health))
+- `routing` (Block List) Routing configuration used to access the instances (see [below for nested schema](#nestedblock--http--routing))
+
+
+### Nested Schema for `http.health`
+
+Required:
+
+- `port` (Number) Health check port on the VM
+- `protocol` (String) Protocol can be http or https
+
+Optional:
+
+- `path` (String) API path to use for health check
+- `status_code_from` (Number) Lower limit for acceptable status code
+- `status_code_to` (Number) Upper limit for acceptable status code
+- `timeout` (Number) Health check timeout
+
+
+
+### Nested Schema for `http.routing`
+
+Required:
+
+- `source_protocol` (String) Source protocol of the proxy can be http or https
+- `target_protocol` (String) Target protocol of the instance can be http or https
+
+Optional:
+
+- `action` (String) Organization Identifier for the Entity
+- `source_port` (Number) Port on the proxy
+- `target_port` (Number) Port on the VM
+
+
+
+
+### Nested Schema for `tcp`
+
+Required:
+
+- `proxy_id` (String) Id of the Proxy
+
+Optional:
+
+- `forward_rule` (Block List) Additional tcp forwarding rules (see [below for nested schema](#nestedblock--tcp--forward_rule))
+- `rdp` (Block List) RDP configuration (see [below for nested schema](#nestedblock--tcp--rdp))
+- `ssh` (Block List) SSH configuration (see [below for nested schema](#nestedblock--tcp--ssh))
+
+
+### Nested Schema for `tcp.forward_rule`
+
+Required:
+
+- `port` (Number) Port to listen on the vm
+
+Optional:
+
+- `connect_on` (Number) Port to listen on the proxy
+
+
+
+### Nested Schema for `tcp.rdp`
+
+Optional:
+
+- `connect_on` (Number) Port to listen on the proxy
+- `port` (Number) Port to listen on the vm
+
+
+
+### Nested Schema for `tcp.ssh`
+
+Optional:
+
+- `connect_on` (Number) Port to listen on the proxy
+- `port` (Number) Port to listen on the vm
diff --git a/docs/resources/autostopping_rule_ecs.md b/docs/resources/autostopping_rule_ecs.md
new file mode 100644
index 000000000..4f359bb80
--- /dev/null
+++ b/docs/resources/autostopping_rule_ecs.md
@@ -0,0 +1,91 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "harness_autostopping_rule_ecs Resource - terraform-provider-harness"
+subcategory: "Next Gen"
+description: |-
+ Resource for creating a Harness Variables.
+---
+
+# harness_autostopping_rule_ecs (Resource)
+
+Resource for creating a Harness Variables.
+
+## Example Usage
+
+```terraform
+resource "harness_autostopping_rule_ecs" "test" {
+ name = "name"
+ cloud_connector_id = "cloud_connector_id"
+ idle_time_mins = 10
+ container {
+ cluster = "cluster"
+ service = "service"
+ region = "us-east-1"
+ task_count = 1
+ }
+ tcp {
+ proxy_id = "proxy_id"
+ forward_rule {
+ port = 2233
+ }
+ }
+ depends {
+ rule_id = 24576
+ delay_in_sec = 5
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `cloud_connector_id` (String) Id of the cloud connector
+- `name` (String) Name of the rule
+
+### Optional
+
+- `container` (Block List, Max: 1) (see [below for nested schema](#nestedblock--container))
+- `custom_domains` (List of String) Custom URLs used to access the instances
+- `depends` (Block List) Dependent rules (see [below for nested schema](#nestedblock--depends))
+- `http` (Block List) Http routing configuration (see [below for nested schema](#nestedblock--http))
+- `idle_time_mins` (Number) Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+- `identifier` (Number) Unique identifier of the resource
+
+
+### Nested Schema for `container`
+
+Required:
+
+- `cluster` (String) Name of cluster in which service belong to
+- `region` (String) Region of cluster
+- `service` (String) Name of service to be onboarded
+
+Optional:
+
+- `task_count` (Number) Desired number of tasks on warming up a rule
+
+
+
+### Nested Schema for `depends`
+
+Required:
+
+- `rule_id` (Number) Rule id of the dependent rule
+
+Optional:
+
+- `delay_in_sec` (Number) Number of seconds the rule should wait after warming up the dependent rule
+
+
+
+### Nested Schema for `http`
+
+Required:
+
+- `proxy_id` (String) Id of the proxy
diff --git a/docs/resources/autostopping_rule_rds.md b/docs/resources/autostopping_rule_rds.md
new file mode 100644
index 000000000..357f8d93c
--- /dev/null
+++ b/docs/resources/autostopping_rule_rds.md
@@ -0,0 +1,94 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "harness_autostopping_rule_rds Resource - terraform-provider-harness"
+subcategory: "Next Gen"
+description: |-
+ Resource for creating a Harness Variables.
+---
+
+# harness_autostopping_rule_rds (Resource)
+
+Resource for creating a Harness Variables.
+
+## Example Usage
+
+```terraform
+resource "harness_autostopping_rule_rds" "test" {
+ name = "name"
+ cloud_connector_id = "cloud_connector_id"
+ idle_time_mins = 10
+ database {
+ id = "database_id"
+ region = "region"
+ }
+ tcp {
+ proxy_id = "proxy_id"
+ forward_rule {
+ port = 2233
+ }
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `cloud_connector_id` (String) Id of the cloud connector
+- `database` (Block List, Min: 1, Max: 1) (see [below for nested schema](#nestedblock--database))
+- `name` (String) Name of the rule
+
+### Optional
+
+- `depends` (Block List) Dependent rules (see [below for nested schema](#nestedblock--depends))
+- `idle_time_mins` (Number) Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.
+- `tcp` (Block List) TCP routing configuration (see [below for nested schema](#nestedblock--tcp))
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+- `identifier` (Number) Unique identifier of the resource
+
+
+### Nested Schema for `database`
+
+Required:
+
+- `id` (String) ID of the database
+- `region` (String) Region to which database belong to
+
+
+
+### Nested Schema for `depends`
+
+Required:
+
+- `rule_id` (Number) Rule id of the dependent rule
+
+Optional:
+
+- `delay_in_sec` (Number) Number of seconds the rule should wait after warming up the dependent rule
+
+
+
+### Nested Schema for `tcp`
+
+Required:
+
+- `proxy_id` (String) Id of the Proxy
+
+Optional:
+
+- `forward_rule` (Block List) Additional tcp forwarding rules (see [below for nested schema](#nestedblock--tcp--forward_rule))
+
+
+### Nested Schema for `tcp.forward_rule`
+
+Required:
+
+- `port` (Number) Port to listen on the vm
+
+Optional:
+
+- `connect_on` (Number) Port to listen on the proxy
diff --git a/docs/resources/autostopping_rule_vm.md b/docs/resources/autostopping_rule_vm.md
new file mode 100644
index 000000000..482cb1722
--- /dev/null
+++ b/docs/resources/autostopping_rule_vm.md
@@ -0,0 +1,210 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "harness_autostopping_rule_vm Resource - terraform-provider-harness"
+subcategory: "Next Gen"
+description: |-
+ Resource for creating a Harness Variables.
+---
+
+# harness_autostopping_rule_vm (Resource)
+
+Resource for creating a Harness Variables.
+
+## Example Usage
+
+```terraform
+resource "harness_autostopping_rule_vm" "test" {
+ name = "name"
+ cloud_connector_id = "cloud_connector_id"
+ idle_time_mins = 10
+ filter {
+ vm_ids = ["/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Compute/virtualMachines/virtual_machine"]
+ regions = ["useast2"]
+ }
+ http {
+ proxy_id = "proxy_id"
+ routing {
+ source_protocol = "https"
+ target_protocol = "https"
+ source_port = 443
+ target_port = 443
+ action = "forward"
+ }
+ routing {
+ source_protocol = "http"
+ target_protocol = "http"
+ source_port = 80
+ target_port = 80
+ action = "forward"
+ }
+ health {
+ protocol = "http"
+ port = 80
+ path = "/"
+ timeout = 30
+ status_code_from = 200
+ status_code_to = 299
+ }
+ }
+ tcp {
+ proxy_id = "proxy_id"
+ ssh {
+ port = 22
+ }
+ rdp {
+ port = 3389
+ }
+ forward_rule {
+ port = 2233
+ }
+ }
+ depends {
+ rule_id = 24576
+ delay_in_sec = 5
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `cloud_connector_id` (String) Id of the cloud connector
+- `filter` (Block List, Min: 1, Max: 1) (see [below for nested schema](#nestedblock--filter))
+- `name` (String) Name of the rule
+
+### Optional
+
+- `custom_domains` (List of String) Custom URLs used to access the instances
+- `depends` (Block List) Dependent rules (see [below for nested schema](#nestedblock--depends))
+- `http` (Block List) Http routing configuration (see [below for nested schema](#nestedblock--http))
+- `idle_time_mins` (Number) Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.
+- `tcp` (Block List) TCP routing configuration (see [below for nested schema](#nestedblock--tcp))
+- `use_spot` (Boolean) Boolean that indicates whether the selected instances should be converted to spot vm
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+- `identifier` (Number) Unique identifier of the resource
+
+
+### Nested Schema for `filter`
+
+Required:
+
+- `vm_ids` (List of String) Ids of instances that needs to be managed using the AutoStopping rules
+
+Optional:
+
+- `regions` (List of String) Regions of instances that needs to be managed using the AutoStopping rules
+- `tags` (Block List) Tags of instances that needs to be managed using the AutoStopping rules (see [below for nested schema](#nestedblock--filter--tags))
+- `zones` (List of String) Zones of instances that needs to be managed using the AutoStopping rules
+
+
+### Nested Schema for `filter.tags`
+
+Required:
+
+- `key` (String)
+- `value` (String)
+
+
+
+
+### Nested Schema for `depends`
+
+Required:
+
+- `rule_id` (Number) Rule id of the dependent rule
+
+Optional:
+
+- `delay_in_sec` (Number) Number of seconds the rule should wait after warming up the dependent rule
+
+
+
+### Nested Schema for `http`
+
+Required:
+
+- `proxy_id` (String) Id of the proxy
+
+Optional:
+
+- `health` (Block List) Health Check Details (see [below for nested schema](#nestedblock--http--health))
+- `routing` (Block List) Routing configuration used to access the instances (see [below for nested schema](#nestedblock--http--routing))
+
+
+### Nested Schema for `http.health`
+
+Required:
+
+- `port` (Number) Health check port on the VM
+- `protocol` (String) Protocol can be http or https
+
+Optional:
+
+- `path` (String) API path to use for health check
+- `status_code_from` (Number) Lower limit for acceptable status code
+- `status_code_to` (Number) Upper limit for acceptable status code
+- `timeout` (Number) Health check timeout
+
+
+
+### Nested Schema for `http.routing`
+
+Required:
+
+- `source_protocol` (String) Source protocol of the proxy can be http or https
+- `target_protocol` (String) Target protocol of the instance can be http or https
+
+Optional:
+
+- `action` (String) Organization Identifier for the Entity
+- `source_port` (Number) Port on the proxy
+- `target_port` (Number) Port on the VM
+
+
+
+
+### Nested Schema for `tcp`
+
+Required:
+
+- `proxy_id` (String) Id of the Proxy
+
+Optional:
+
+- `forward_rule` (Block List) Additional tcp forwarding rules (see [below for nested schema](#nestedblock--tcp--forward_rule))
+- `rdp` (Block List) RDP configuration (see [below for nested schema](#nestedblock--tcp--rdp))
+- `ssh` (Block List) SSH configuration (see [below for nested schema](#nestedblock--tcp--ssh))
+
+
+### Nested Schema for `tcp.forward_rule`
+
+Required:
+
+- `port` (Number) Port to listen on the vm
+
+Optional:
+
+- `connect_on` (Number) Port to listen on the proxy
+
+
+
+### Nested Schema for `tcp.rdp`
+
+Optional:
+
+- `connect_on` (Number) Port to listen on the proxy
+- `port` (Number) Port to listen on the vm
+
+
+
+### Nested Schema for `tcp.ssh`
+
+Optional:
+
+- `connect_on` (Number) Port to listen on the proxy
+- `port` (Number) Port to listen on the vm
diff --git a/examples/data-sources/harness_autostopping_rule_ecs/data-source.tf b/examples/data-sources/harness_autostopping_rule_ecs/data-source.tf
new file mode 100644
index 000000000..d8b5de01b
--- /dev/null
+++ b/examples/data-sources/harness_autostopping_rule_ecs/data-source.tf
@@ -0,0 +1,3 @@
+data "harness_autostopping_rule_ecs" "example" {
+ identifier = "identifier"
+}
diff --git a/examples/data-sources/harness_autostopping_rule_rds/data-source.tf b/examples/data-sources/harness_autostopping_rule_rds/data-source.tf
new file mode 100644
index 000000000..f818e0844
--- /dev/null
+++ b/examples/data-sources/harness_autostopping_rule_rds/data-source.tf
@@ -0,0 +1,3 @@
+data "harness_autostopping_rule_rds" "example" {
+ identifier = "identifier"
+}
diff --git a/examples/data-sources/harness_autostopping_rule_vm/data-source.tf b/examples/data-sources/harness_autostopping_rule_vm/data-source.tf
new file mode 100644
index 000000000..c6a4cd782
--- /dev/null
+++ b/examples/data-sources/harness_autostopping_rule_vm/data-source.tf
@@ -0,0 +1,3 @@
+data "harness_autostopping_rule_vm" "example" {
+ identifier = "identifier"
+}
diff --git a/examples/resources/harness_autostopping_azure_proxy/resource.tf b/examples/resources/harness_autostopping_azure_proxy/resource.tf
index 8e300746c..4c6d71f4f 100644
--- a/examples/resources/harness_autostopping_azure_proxy/resource.tf
+++ b/examples/resources/harness_autostopping_azure_proxy/resource.tf
@@ -1,15 +1,15 @@
resource "harness_autostopping_azure_proxy" "test" {
- name = "name"
- cloud_connector_id = "cloud_connector_id"
- host_name = "host_name"
- region = "eastus2"
- resource_group = "resource_group"
- vpc = "/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Network/virtualNetworks/virtual_network"
- subnet_id = "/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Network/virtualNetworks/virtual_network/subnets/subnet_id"
- security_groups =["/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Network/networkSecurityGroups/network_security_group"]
- allocate_static_ip = true
- machine_type = "Standard_D2s_v3"
- keypair = ""
- api_key = ""
+ name = "name"
+ cloud_connector_id = "cloud_connector_id"
+ host_name = "host_name"
+ region = "eastus2"
+ resource_group = "resource_group"
+ vpc = "/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Network/virtualNetworks/virtual_network"
+ subnet_id = "/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Network/virtualNetworks/virtual_network/subnets/subnet_id"
+ security_groups = ["/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Network/networkSecurityGroups/network_security_group"]
+ allocate_static_ip = true
+ machine_type = "Standard_D2s_v3"
+ keypair = ""
+ api_key = ""
}
diff --git a/examples/resources/harness_autostopping_rule_ecs/resource.tf b/examples/resources/harness_autostopping_rule_ecs/resource.tf
new file mode 100644
index 000000000..afa78890e
--- /dev/null
+++ b/examples/resources/harness_autostopping_rule_ecs/resource.tf
@@ -0,0 +1,21 @@
+resource "harness_autostopping_rule_ecs" "test" {
+ name = "name"
+ cloud_connector_id = "cloud_connector_id"
+ idle_time_mins = 10
+ container {
+ cluster = "cluster"
+ service = "service"
+ region = "us-east-1"
+ task_count = 1
+ }
+ tcp {
+ proxy_id = "proxy_id"
+ forward_rule {
+ port = 2233
+ }
+ }
+ depends {
+ rule_id = 24576
+ delay_in_sec = 5
+ }
+}
diff --git a/examples/resources/harness_autostopping_rule_rds/resource.tf b/examples/resources/harness_autostopping_rule_rds/resource.tf
new file mode 100644
index 000000000..7ff8a985f
--- /dev/null
+++ b/examples/resources/harness_autostopping_rule_rds/resource.tf
@@ -0,0 +1,15 @@
+resource "harness_autostopping_rule_rds" "test" {
+ name = "name"
+ cloud_connector_id = "cloud_connector_id"
+ idle_time_mins = 10
+ database {
+ id = "database_id"
+ region = "region"
+ }
+ tcp {
+ proxy_id = "proxy_id"
+ forward_rule {
+ port = 2233
+ }
+ }
+}
diff --git a/examples/resources/harness_autostopping_rule_vm/resource.tf b/examples/resources/harness_autostopping_rule_vm/resource.tf
new file mode 100644
index 000000000..63637076d
--- /dev/null
+++ b/examples/resources/harness_autostopping_rule_vm/resource.tf
@@ -0,0 +1,50 @@
+resource "harness_autostopping_rule_vm" "test" {
+ name = "name"
+ cloud_connector_id = "cloud_connector_id"
+ idle_time_mins = 10
+ filter {
+ vm_ids = ["/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Compute/virtualMachines/virtual_machine"]
+ regions = ["useast2"]
+ }
+ http {
+ proxy_id = "proxy_id"
+ routing {
+ source_protocol = "https"
+ target_protocol = "https"
+ source_port = 443
+ target_port = 443
+ action = "forward"
+ }
+ routing {
+ source_protocol = "http"
+ target_protocol = "http"
+ source_port = 80
+ target_port = 80
+ action = "forward"
+ }
+ health {
+ protocol = "http"
+ port = 80
+ path = "/"
+ timeout = 30
+ status_code_from = 200
+ status_code_to = 299
+ }
+ }
+ tcp {
+ proxy_id = "proxy_id"
+ ssh {
+ port = 22
+ }
+ rdp {
+ port = 3389
+ }
+ forward_rule {
+ port = 2233
+ }
+ }
+ depends {
+ rule_id = 24576
+ delay_in_sec = 5
+ }
+}
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index c97c203c0..b922205d9 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -36,6 +36,7 @@ import (
"github.com/harness/terraform-provider-harness/internal/service/cd/yamlconfig"
pl_apikey "github.com/harness/terraform-provider-harness/internal/service/platform/api_key"
"github.com/harness/terraform-provider-harness/internal/service/platform/autostopping/load_balancer"
+ as_rule "github.com/harness/terraform-provider-harness/internal/service/platform/autostopping/rule"
"github.com/harness/terraform-provider-harness/internal/service/platform/ccm_filters"
"github.com/harness/terraform-provider-harness/internal/service/platform/connector"
pl_current_user "github.com/harness/terraform-provider-harness/internal/service/platform/current_user"
@@ -54,6 +55,7 @@ import (
gitops_repo_cert "github.com/harness/terraform-provider-harness/internal/service/platform/gitops/repository_certificates"
gitops_repo_cred "github.com/harness/terraform-provider-harness/internal/service/platform/gitops/repository_credentials"
pl_infrastructure "github.com/harness/terraform-provider-harness/internal/service/platform/infrastructure"
+
"github.com/harness/terraform-provider-harness/internal/service/platform/input_set"
"github.com/harness/terraform-provider-harness/internal/service/platform/monitored_service"
"github.com/harness/terraform-provider-harness/internal/service/platform/organization"
@@ -229,6 +231,9 @@ func Provider(version string) func() *schema.Provider {
"harness_platform_connector_service_now": connector.DataSourceConnectorSerivceNow(),
"harness_platform_apikey": pl_apikey.DataSourceApiKey(),
"harness_platform_token": pl_token.DataSourceToken(),
+ "harness_autostopping_rule_vm": as_rule.DataSourceVMRule(),
+ "harness_autostopping_rule_rds": as_rule.DataSourceRDSRule(),
+ "harness_autostopping_rule_ecs": as_rule.DataSourceECSRule(),
"harness_platform_file_store_file": file_store.DataSourceFileStoreNodeFile(),
"harness_platform_file_store_folder": file_store.DataSourceFileStoreNodeFolder(),
"harness_autostopping_azure_proxy": load_balancer.DataSourceAzureProxy(),
@@ -352,6 +357,9 @@ func Provider(version string) func() *schema.Provider {
"harness_platform_connector_service_now": connector.ResourceConnectorServiceNow(),
"harness_platform_apikey": pl_apikey.ResourceApiKey(),
"harness_platform_token": pl_token.ResourceToken(),
+ "harness_autostopping_rule_vm": as_rule.ResourceVMRule(),
+ "harness_autostopping_rule_rds": as_rule.ResourceRDSRule(),
+ "harness_autostopping_rule_ecs": as_rule.ResourceECSRule(),
"harness_platform_file_store_file": file_store.ResourceFileStoreNodeFile(),
"harness_platform_file_store_folder": file_store.ResourceFileStoreNodeFolder(),
"harness_autostopping_azure_proxy": load_balancer.ResourceAzureProxy(),
diff --git a/internal/service/platform/autostopping/rule/as_ecs.go b/internal/service/platform/autostopping/rule/as_ecs.go
new file mode 100644
index 000000000..03c60dc68
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_ecs.go
@@ -0,0 +1,125 @@
+package as_rule
+
+import (
+ "context"
+
+ "github.com/harness/terraform-provider-harness/helpers"
+ "github.com/harness/terraform-provider-harness/internal"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func ResourceECSRule() *schema.Resource {
+ resource := &schema.Resource{
+ Description: "Resource for creating a Harness Variables.",
+
+ ReadContext: resourceASRuleRead,
+ CreateContext: resourceECSRuleCreateOrUpdate,
+ UpdateContext: resourceECSRuleCreateOrUpdate,
+ DeleteContext: resourceASRuleDelete,
+ Importer: helpers.MultiLevelResourceImporter,
+ Schema: map[string]*schema.Schema{
+ "identifier": {
+ Description: "Unique identifier of the resource",
+ Type: schema.TypeFloat,
+ Computed: true,
+ },
+ "name": {
+ Description: "Name of the rule",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "cloud_connector_id": {
+ Description: "Id of the cloud connector",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "idle_time_mins": {
+ Description: "Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 15,
+ },
+ "custom_domains": {
+ Description: "Custom URLs used to access the instances",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "container": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "cluster": {
+ Type: schema.TypeString,
+ Description: "Name of cluster in which service belong to",
+ Required: true,
+ },
+ "service": {
+ Type: schema.TypeString,
+ Description: "Name of service to be onboarded",
+ Required: true,
+ },
+ "region": {
+ Type: schema.TypeString,
+ Description: "Region of cluster",
+ Required: true,
+ },
+ "task_count": {
+ Type: schema.TypeInt,
+ Description: "Desired number of tasks on warming up a rule",
+ Optional: true,
+ Default: 1,
+ },
+ },
+ },
+ },
+ "http": {
+ Description: "Http routing configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "proxy_id": {
+ Description: "Id of the proxy",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ },
+ },
+ },
+ "depends": {
+ Description: "Dependent rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "rule_id": {
+ Description: "Rule id of the dependent rule",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ "delay_in_sec": {
+ Description: "Number of seconds the rule should wait after warming up the dependent rule",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 5,
+ },
+ },
+ },
+ },
+ },
+ }
+
+ return resource
+}
+
+func resourceECSRuleCreateOrUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)
+ saveServiceRequestV2 := buildASRule(d, ECS, c.AccountId)
+ return resourceASRuleCreateOrUpdate(ctx, d, meta, saveServiceRequestV2)
+}
diff --git a/internal/service/platform/autostopping/rule/as_ecs_data_source.go b/internal/service/platform/autostopping/rule/as_ecs_data_source.go
new file mode 100644
index 000000000..ea7af0bc4
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_ecs_data_source.go
@@ -0,0 +1,110 @@
+package as_rule
+
+import (
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func DataSourceECSRule() *schema.Resource {
+ resource := &schema.Resource{
+ Description: "Data source for retrieving a Harness Variable.",
+ ReadContext: resourceASRuleRead,
+
+ Schema: map[string]*schema.Schema{
+ "identifier": {
+ Description: "Unique identifier of the resource",
+ Type: schema.TypeFloat,
+ Computed: true,
+ },
+ "name": {
+ Description: "Name of the rule",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "cloud_connector_id": {
+ Description: "Id of the cloud connector",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "idle_time_mins": {
+ Description: "Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 15,
+ },
+ "custom_domains": {
+ Description: "Custom URLs used to access the instances",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "container": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "cluster": {
+ Type: schema.TypeString,
+ Description: "Name of cluster in which service belong to",
+ Required: true,
+ },
+ "service": {
+ Type: schema.TypeString,
+ Description: "Name of service to be onboarded",
+ Required: true,
+ },
+ "region": {
+ Type: schema.TypeString,
+ Description: "Region of cluster",
+ Required: true,
+ },
+ "task_count": {
+ Type: schema.TypeInt,
+ Description: "Desired number of tasks on warming up a rule",
+ Optional: true,
+ Default: 1,
+ },
+ },
+ },
+ },
+ "http": {
+ Description: "Http routing configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "proxy_id": {
+ Description: "Id of the proxy",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ },
+ },
+ },
+ "depends": {
+ Description: "Dependent rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "rule_id": {
+ Description: "Rule id of the dependent rule",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ "delay_in_sec": {
+ Description: "Number of seconds the rule should wait after warming up the dependent rule",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 5,
+ },
+ },
+ },
+ },
+ },
+ }
+
+ return resource
+}
diff --git a/internal/service/platform/autostopping/rule/as_ecs_test.go b/internal/service/platform/autostopping/rule/as_ecs_test.go
new file mode 100644
index 000000000..726ff4d4d
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_ecs_test.go
@@ -0,0 +1,51 @@
+package as_rule_test
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/harness/terraform-provider-harness/internal/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestResourceECSRule(t *testing.T) {
+ name := "terraform-rule-test"
+ resourceName := "harness_autostopping_rule_ecs.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProviderFactories: acctest.ProviderFactories,
+ // CheckDestroy: testRuleDestroy(resourceName),
+ Steps: []resource.TestStep{
+ {
+ Config: testECSRule(name),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "name", name),
+ ),
+ },
+ },
+ })
+}
+
+func testECSRule(name string) string {
+ return fmt.Sprintf(`
+ resource "harness_autostopping_rule_ecs" "test" {
+ name = "%[1]s"
+ cloud_connector_id = "Azure_SE"
+ idle_time_mins = 10
+ container {
+ cluster = "cluster"
+ service = "service"
+ region = "us-east-1"
+ task_count = 1
+ }
+ http {
+ proxy_id = "ap-chdpf8f83v0c1aj69oog"
+ }
+ depends {
+ rule_id = 24576
+ delay_in_sec = 5
+ }
+ }
+`, name)
+}
diff --git a/internal/service/platform/autostopping/rule/as_rds.go b/internal/service/platform/autostopping/rule/as_rds.go
new file mode 100644
index 000000000..e239748a5
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_rds.go
@@ -0,0 +1,125 @@
+package as_rule
+
+import (
+ "context"
+
+ "github.com/harness/terraform-provider-harness/helpers"
+ "github.com/harness/terraform-provider-harness/internal"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func ResourceRDSRule() *schema.Resource {
+ resource := &schema.Resource{
+ Description: "Resource for creating a Harness Variables.",
+
+ ReadContext: resourceASRuleRead,
+ UpdateContext: resourceRDSRuleCreateOrUpdate,
+ DeleteContext: resourceASRuleDelete,
+ CreateContext: resourceRDSRuleCreateOrUpdate,
+ Importer: helpers.MultiLevelResourceImporter,
+ Schema: map[string]*schema.Schema{
+ "identifier": {
+ Description: "Unique identifier of the resource",
+ Type: schema.TypeFloat,
+ Computed: true,
+ },
+ "name": {
+ Description: "Name of the rule",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "cloud_connector_id": {
+ Description: "Id of the cloud connector",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "idle_time_mins": {
+ Description: "Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 15,
+ },
+ "database": {
+ Type: schema.TypeList,
+ Required: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "id": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "ID of the database",
+ },
+ "region": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Region to which database belong to",
+ },
+ },
+ },
+ },
+ "tcp": {
+ Description: "TCP routing configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "proxy_id": {
+ Description: "Id of the Proxy",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "forward_rule": {
+ Description: "Additional tcp forwarding rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "connect_on": {
+ Description: "Port to listen on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "port": {
+ Description: "Port to listen on the vm",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "depends": {
+ Description: "Dependent rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "rule_id": {
+ Description: "Rule id of the dependent rule",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ "delay_in_sec": {
+ Description: "Number of seconds the rule should wait after warming up the dependent rule",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 5,
+ },
+ },
+ },
+ },
+ },
+ }
+
+ return resource
+}
+
+func resourceRDSRuleCreateOrUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)
+ saveServiceRequestV2 := buildASRule(d, Database, c.AccountId)
+ return resourceASRuleCreateOrUpdate(ctx, d, meta, saveServiceRequestV2)
+}
diff --git a/internal/service/platform/autostopping/rule/as_rds_data_source.go b/internal/service/platform/autostopping/rule/as_rds_data_source.go
new file mode 100644
index 000000000..298addce7
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_rds_data_source.go
@@ -0,0 +1,110 @@
+package as_rule
+
+import (
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func DataSourceRDSRule() *schema.Resource {
+ resource := &schema.Resource{
+ Description: "Data source for retrieving a Harness Variable.",
+ ReadContext: resourceASRuleRead,
+
+ Schema: map[string]*schema.Schema{
+ "identifier": {
+ Description: "Unique identifier of the resource",
+ Type: schema.TypeFloat,
+ Computed: true,
+ },
+ "name": {
+ Description: "Name of the rule",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "cloud_connector_id": {
+ Description: "Id of the cloud connector",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "idle_time_mins": {
+ Description: "Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 15,
+ },
+ "database": {
+ Type: schema.TypeList,
+ Required: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "id": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "ID of the database",
+ },
+ "region": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Region to which database belong to",
+ },
+ },
+ },
+ },
+ "tcp": {
+ Description: "TCP routing configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "proxy_id": {
+ Description: "Id of the Proxy",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "forward_rule": {
+ Description: "Additional tcp forwarding rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "connect_on": {
+ Description: "Port to listen on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "port": {
+ Description: "Port to listen on the vm",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "depends": {
+ Description: "Dependent rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "rule_id": {
+ Description: "Rule id of the dependent rule",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ "delay_in_sec": {
+ Description: "Number of seconds the rule should wait after warming up the dependent rule",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 5,
+ },
+ },
+ },
+ },
+ },
+ }
+
+ return resource
+}
diff --git a/internal/service/platform/autostopping/rule/as_rds_test.go b/internal/service/platform/autostopping/rule/as_rds_test.go
new file mode 100644
index 000000000..131acfd7c
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_rds_test.go
@@ -0,0 +1,75 @@
+package as_rule_test
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/harness/terraform-provider-harness/internal/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestResourceRDSRule(t *testing.T) {
+ name := "terraform-rule-test-rds"
+ resourceName := "harness_autostopping_rule_rds.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProviderFactories: acctest.ProviderFactories,
+ // CheckDestroy: testRuleDestroy(resourceName),
+ Steps: []resource.TestStep{
+ {
+ Config: testRDSRule(name),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "name", name),
+ ),
+ },
+ {
+ Config: testRDSRuleUpdate(name, "15"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "name", name),
+ resource.TestCheckResourceAttr(resourceName, "idle_time_mins", "15"),
+ ),
+ },
+ },
+ })
+}
+
+func testRDSRule(name string) string {
+ return fmt.Sprintf(`
+ resource "harness_autostopping_rule_rds" "test" {
+ name = "%[1]s"
+ cloud_connector_id = "DoNotDelete_LightwingNonProd"
+ idle_time_mins = 10
+ database {
+ id = "database_id"
+ region = "us-east-1"
+ }
+ tcp {
+ proxy_id = "ap-ciun1635us1fhpjiotfg"
+ forward_rule {
+ port = 2233
+ }
+ }
+ }
+`, name)
+}
+
+func testRDSRuleUpdate(name string, idleTime string) string {
+ return fmt.Sprintf(`
+ resource "harness_autostopping_rule_rds" "test" {
+ name = "%[1]s"
+ cloud_connector_id = "DoNotDelete_LightwingNonProd"
+ idle_time_mins = %[2]s
+ database {
+ id = "database_id"
+ region = "us-east-1"
+ }
+ tcp {
+ proxy_id = "ap-ciun1635us1fhpjiotfg"
+ forward_rule {
+ port = 2233
+ }
+ }
+ }
+`, name, idleTime)
+}
diff --git a/internal/service/platform/autostopping/rule/as_rule.go b/internal/service/platform/autostopping/rule/as_rule.go
new file mode 100644
index 000000000..190c29d9d
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_rule.go
@@ -0,0 +1,364 @@
+package as_rule
+
+import (
+ "context"
+ "net/http"
+ "strconv"
+
+ "github.com/harness/harness-go-sdk/harness/nextgen"
+ "github.com/harness/terraform-provider-harness/helpers"
+ "github.com/harness/terraform-provider-harness/internal"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+const (
+ Database = "database"
+ Instance = "instance"
+ ECS = "containers"
+)
+
+func resourceASRuleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)
+
+ ruleId, err := strconv.ParseFloat(d.Id(), 64)
+ if err != nil {
+ return diag.Errorf("invalid rule id")
+ }
+ resp, httpResp, err := c.CloudCostAutoStoppingRulesApi.AutoStoppingRuleDetails(ctx, c.AccountId, ruleId, c.AccountId)
+
+ if err != nil {
+ return helpers.HandleReadApiError(err, d, httpResp)
+ }
+
+ if resp.Response != nil {
+ readASRule(d, resp.Response.Service.Id)
+ }
+
+ return nil
+}
+
+func resourceASRuleCreateOrUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}, rule nextgen.SaveServiceRequestV2) diag.Diagnostics {
+ c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)
+
+ var err error
+ var resp nextgen.RuleResponse
+ var httpResp *http.Response
+
+ id := d.Id()
+
+ if id == "" {
+ resp, httpResp, err = c.CloudCostAutoStoppingRulesV2Api.CreateAutoStoppingRuleV2(ctx, rule, c.AccountId, c.AccountId)
+ } else {
+ resp, httpResp, err = c.CloudCostAutoStoppingRulesV2Api.UpdateAutoStoppingRuleV2(ctx, rule, c.AccountId, c.AccountId, id)
+ }
+
+ if err != nil {
+ return helpers.HandleApiError(err, d, httpResp)
+ }
+
+ if resp.Response != nil {
+ readASRule(d, resp.Response.Id)
+ }
+
+ return nil
+}
+
+func resourceASRuleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)
+ ruleId, err := strconv.ParseFloat(d.Id(), 64)
+ if err != nil {
+ return diag.Errorf("invalid rule id")
+ }
+ httpResp, err := c.CloudCostAutoStoppingRulesApi.DeleteAutoStoppingRule(ctx, ruleId, c.AccountId, c.AccountId)
+ if err != nil {
+ return helpers.HandleApiError(err, d, httpResp)
+ }
+ return nil
+}
+
+func buildASRule(d *schema.ResourceData, kind string, accountId string) nextgen.SaveServiceRequestV2 {
+ serviceV2 := &nextgen.ServiceV2{}
+ serviceV2.AccountIdentifier = accountId
+ serviceV2.Kind = kind
+ if attr, ok := d.GetOk("name"); ok {
+ serviceV2.Name = attr.(string)
+ }
+
+ if attr, ok := d.GetOk("cloud_connector_id"); ok {
+ serviceV2.CloudAccountId = attr.(string)
+ }
+ serviceV2.Fulfilment = "ondemand"
+ if attr, ok := d.GetOk("use_spot"); ok {
+ onDemand := attr.(bool)
+ if onDemand {
+ serviceV2.Fulfilment = "ondemand"
+ } else {
+ serviceV2.Fulfilment = "spot"
+ }
+ }
+ serviceV2.IdleTimeMins = 15
+ if attr, ok := d.GetOk("idle_time_mins"); ok {
+ serviceV2.IdleTimeMins = attr.(int)
+ }
+
+ if attr, ok := d.GetOk("custom_domains"); ok {
+ domains := make([]string, 0)
+ for _, v := range attr.([]interface{}) {
+ domains = append(domains, v.(string))
+ }
+ serviceV2.CustomDomains = domains
+ }
+ routingData := &nextgen.RoutingDataV2{}
+ httpProxy, tcpProxy, healthCheck := getRoutingConfigurations(d)
+ if httpProxy != nil {
+ routingData.Http = httpProxy
+ }
+ if tcpProxy != nil {
+ routingData.Tcp = tcpProxy
+ }
+ if healthCheck != nil {
+ serviceV2.HealthCheck = healthCheck
+ }
+
+ rdsDatabase := getDatabaseConfig(d)
+ if rdsDatabase != nil {
+ routingData.Database = rdsDatabase
+ }
+
+ containerSvc := getContainerConfig(d)
+ if containerSvc != nil {
+ routingData.ContainerSvc = containerSvc
+ }
+
+ if attr, ok := d.GetOk("filter"); ok {
+ filter := &nextgen.FilterObject{}
+ filterObj := attr.([]interface{})[0].(map[string]interface{})
+ if attr, ok := filterObj["vm_ids"]; ok {
+ vmIds := make([]string, 0)
+ for _, v := range attr.([]interface{}) {
+ vmIds = append(vmIds, v.(string))
+ }
+ filter.Ids = vmIds
+ }
+ if attr, ok := filterObj["regions"]; ok {
+ regions := make([]string, 0)
+ for _, v := range attr.([]interface{}) {
+ regions = append(regions, v.(string))
+ }
+ filter.Regions = regions
+ }
+ if attr, ok := filterObj["zones"]; ok {
+ zones := make([]string, 0)
+ for _, v := range attr.([]interface{}) {
+ zones = append(zones, v.(string))
+ }
+ filter.Zones = zones
+ }
+ if attr, ok := filterObj["tags"]; ok {
+ filter.Tags = make(map[string]string)
+ for _, tag := range attr.([]interface{}) {
+ item := tag.(map[string]interface{})
+ filter.Tags[item["key"].(string)] = item["value"].(string)
+ }
+ }
+ routingData.Instance = &nextgen.InstanceBasedRoutingDataV2{}
+ routingData.Instance.Filter = filter
+ }
+
+ serviceV2.Routing = routingData
+ deps := getDependencies(d)
+ saveServiceRequestV2 := &nextgen.SaveServiceRequestV2{
+ Service: serviceV2,
+ Deps: deps,
+ }
+ return *saveServiceRequestV2
+}
+
+func getDatabaseConfig(d *schema.ResourceData) *nextgen.RdsDatabase {
+ var rdsDatabase *nextgen.RdsDatabase
+ if attr, ok := d.GetOk("database"); ok {
+ rdsDatabase = &nextgen.RdsDatabase{}
+ databaseObj := attr.([]interface{})[0].(map[string]interface{})
+ if attr, ok := databaseObj["id"]; ok {
+ rdsDatabase.Id = attr.(string)
+ }
+ if attr, ok := databaseObj["region"]; ok {
+ rdsDatabase.Region = attr.(string)
+ }
+ }
+ return rdsDatabase
+}
+
+func getContainerConfig(d *schema.ResourceData) *nextgen.ContainerSvc {
+ var containerSvc *nextgen.ContainerSvc
+ if attr, ok := d.GetOk("container"); ok {
+ containerSvc = &nextgen.ContainerSvc{}
+ databaseObj := attr.([]interface{})[0].(map[string]interface{})
+ if attr, ok := databaseObj["cluster"]; ok {
+ containerSvc.Cluster = attr.(string)
+ }
+ if attr, ok := databaseObj["region"]; ok {
+ containerSvc.Region = attr.(string)
+ }
+ if attr, ok := databaseObj["service"]; ok {
+ containerSvc.Service = attr.(string)
+ }
+ containerSvc.TaskCount = 1
+ if attr, ok := databaseObj["task_count"]; ok {
+ desCount, ok := attr.(int64)
+ if ok {
+ containerSvc.TaskCount = float64(desCount)
+ }
+ }
+ }
+ return containerSvc
+}
+
+func getDependencies(d *schema.ResourceData) []nextgen.ServiceDep {
+ dependencies := d.Get("depends").([]interface{})
+ dependencyList := make([]nextgen.ServiceDep, 0)
+ if len(dependencies) == 0 {
+ return dependencyList
+ }
+ for _, dep := range dependencies {
+ id := dep.(map[string]interface{})["rule_id"].(int)
+ delay := dep.(map[string]interface{})["delay_in_sec"].(int)
+ dependency := &nextgen.ServiceDep{
+ DepId: int64(id),
+ DelaySecs: int32(delay),
+ }
+ dependencyList = append(dependencyList, *dependency)
+ }
+ return dependencyList
+}
+
+func getRoutingConfigurations(d *schema.ResourceData) (*nextgen.HttpProxy, *nextgen.TcpProxy, *nextgen.HealthCheck) {
+ var httpProxy *nextgen.HttpProxy
+ var tcpProxy *nextgen.TcpProxy
+ var healthCheck *nextgen.HealthCheck
+ if attr, ok := d.GetOk("http"); ok {
+ httpProxy = &nextgen.HttpProxy{}
+ httpRoutingObj := attr.([]interface{})[0].(map[string]interface{})
+
+ if attr, ok := httpRoutingObj["proxy_id"]; ok {
+ proxy := &nextgen.Proxy{
+ Id: attr.(string),
+ }
+ httpProxy.Proxy = proxy
+ }
+ if attr, ok := httpRoutingObj["routing"]; ok {
+ routingConfigs := attr.([]interface{})
+ portConfigsList := make([]nextgen.PortConfig, 0)
+ for _, routingConfig := range routingConfigs {
+ routingObj := routingConfig.(map[string]interface{})
+ portConfig := &nextgen.PortConfig{}
+ if attr, ok := routingObj["source_protocol"]; ok {
+ portConfig.Protocol = attr.(string)
+ }
+ if attr, ok := routingObj["target_protocol"]; ok {
+ portConfig.TargetProtocol = attr.(string)
+ }
+ if attr, ok := routingObj["source_port"]; ok {
+ portConfig.Port = attr.(int)
+ }
+ if attr, ok := routingObj["target_port"]; ok {
+ portConfig.TargetPort = attr.(int)
+ }
+ if attr, ok := routingObj["action"]; ok {
+ portConfig.Action = attr.(string)
+ }
+ portConfig.RoutingRules = []nextgen.RoutingRule{}
+
+ portConfigsList = append(portConfigsList, *portConfig)
+ }
+ httpProxy.Ports = portConfigsList
+ }
+ if attr, ok := httpRoutingObj["health"]; ok {
+ healthCheck = &nextgen.HealthCheck{}
+ healthConfig := attr.([]interface{})[0].(map[string]interface{})
+ if attr, ok := healthConfig["protocol"]; ok {
+ healthCheck.Protocol = attr.(string)
+ }
+ if attr, ok := healthConfig["port"]; ok {
+ healthCheck.Port = attr.(int)
+ }
+ if attr, ok := healthConfig["path"]; ok {
+ healthCheck.Path = attr.(string)
+ }
+ if attr, ok := healthConfig["timeout"]; ok {
+ healthCheck.Timeout = attr.(int)
+ }
+ if attr, ok := healthConfig["status_code_from"]; ok {
+ healthCheck.StatusCodeFrom = attr.(int)
+ }
+ if attr, ok := healthConfig["status_code_to"]; ok {
+ healthCheck.StatusCodeTo = attr.(int)
+ }
+ }
+ }
+
+ if attr, ok := d.GetOk("tcp"); ok {
+ tcpProxy = &nextgen.TcpProxy{}
+ tcpRoutingObj := attr.([]interface{})[0].(map[string]interface{})
+
+ if attr, ok := tcpRoutingObj["proxy_id"]; ok {
+ proxy := &nextgen.Proxy{
+ Id: attr.(string),
+ }
+ tcpProxy.Proxy = proxy
+ }
+ if attr, ok := tcpRoutingObj["ssh"]; ok {
+ if valArr, ok := attr.([]interface{}); ok && len(valArr) > 0 {
+ sshConfig := valArr[0].(map[string]interface{})
+ ssh := &nextgen.ServiceRoutingTcpPort{}
+ if attr, ok := sshConfig["connect_on"]; ok {
+ ssh.Source = attr.(int)
+ }
+ ssh.Target = 22
+ if attr, ok := sshConfig["port"]; ok {
+ ssh.Target = attr.(int)
+ }
+ tcpProxy.SshConf = ssh
+ }
+ }
+ if attr, ok := tcpRoutingObj["rdp"]; ok {
+ if valArr, ok := attr.([]interface{}); ok && len(valArr) > 0 {
+ rdpConfig := valArr[0].(map[string]interface{})
+ rdp := &nextgen.ServiceRoutingTcpPort{}
+ if attr, ok := rdpConfig["connect_on"]; ok {
+ rdp.Source = attr.(int)
+ }
+ rdp.Target = 3389
+ if attr, ok := rdpConfig["port"]; ok {
+ rdp.Target = attr.(int)
+ }
+ tcpProxy.RdpConf = rdp
+ }
+ }
+ if attr, ok := tcpRoutingObj["forward_rule"]; ok {
+ forwardRules := attr.([]interface{})
+ tcpPortList := make([]nextgen.ServiceRoutingTcpPort, 0)
+ for _, forwardRule := range forwardRules {
+ rule := forwardRule.(map[string]interface{})
+ tcpPort := &nextgen.ServiceRoutingTcpPort{}
+ if attr, ok := rule["connect_on"]; ok {
+ tcpPort.Source = attr.(int)
+ }
+ if attr, ok := rule["port"]; ok {
+ tcpPort.Target = attr.(int)
+ }
+ tcpPortList = append(tcpPortList, *tcpPort)
+ }
+ tcpProxy.CustomPorts = tcpPortList
+ }
+ }
+
+ return httpProxy, tcpProxy, healthCheck
+}
+
+func readASRule(d *schema.ResourceData, id int64) {
+ identifier := strconv.Itoa(int(id))
+ d.SetId(identifier)
+ d.Set("identifier", identifier)
+}
diff --git a/internal/service/platform/autostopping/rule/as_vm.go b/internal/service/platform/autostopping/rule/as_vm.go
new file mode 100644
index 000000000..32fb71772
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_vm.go
@@ -0,0 +1,298 @@
+package as_rule
+
+import (
+ "context"
+
+ "github.com/harness/terraform-provider-harness/helpers"
+ "github.com/harness/terraform-provider-harness/internal"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func ResourceVMRule() *schema.Resource {
+ resource := &schema.Resource{
+ Description: "Resource for creating a Harness Variables.",
+
+ ReadContext: resourceASRuleRead,
+ UpdateContext: resourceVMRuleCreateOrUpdate,
+ DeleteContext: resourceASRuleDelete,
+ CreateContext: resourceVMRuleCreateOrUpdate,
+ Importer: helpers.MultiLevelResourceImporter,
+ Schema: map[string]*schema.Schema{
+ "identifier": {
+ Description: "Unique identifier of the resource",
+ Type: schema.TypeFloat,
+ Computed: true,
+ },
+ "name": {
+ Description: "Name of the rule",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "cloud_connector_id": {
+ Description: "Id of the cloud connector",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "idle_time_mins": {
+ Description: "Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 15,
+ },
+ "use_spot": {
+ Description: "Boolean that indicates whether the selected instances should be converted to spot vm",
+ Type: schema.TypeBool,
+ Default: false,
+ Optional: true,
+ },
+ "custom_domains": {
+ Description: "Custom URLs used to access the instances",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "filter": {
+ Type: schema.TypeList,
+ Required: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "vm_ids": {
+ Description: "Ids of instances that needs to be managed using the AutoStopping rules",
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "tags": {
+ Description: "Tags of instances that needs to be managed using the AutoStopping rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "key": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "value": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ },
+ },
+ },
+ "regions": {
+ Description: "Regions of instances that needs to be managed using the AutoStopping rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "zones": {
+ Description: "Zones of instances that needs to be managed using the AutoStopping rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ },
+ },
+ },
+ "http": {
+ Description: "Http routing configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "proxy_id": {
+ Description: "Id of the proxy",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "routing": {
+ Description: "Routing configuration used to access the instances",
+ Type: schema.TypeList,
+ MinItems: 1,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "source_protocol": {
+ Description: "Source protocol of the proxy can be http or https",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "target_protocol": {
+ Description: "Target protocol of the instance can be http or https",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "source_port": {
+ Description: "Port on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "target_port": {
+ Description: "Port on the VM",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "action": {
+ Description: "Organization Identifier for the Entity",
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "health": {
+ Description: "Health Check Details",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "protocol": {
+ Description: "Protocol can be http or https",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "port": {
+ Description: "Health check port on the VM",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ "path": {
+ Description: "API path to use for health check",
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "timeout": {
+ Description: "Health check timeout",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "status_code_from": {
+ Description: "Lower limit for acceptable status code",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "status_code_to": {
+ Description: "Upper limit for acceptable status code",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "tcp": {
+ Description: "TCP routing configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "proxy_id": {
+ Description: "Id of the Proxy",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "ssh": {
+ Description: "SSH configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "connect_on": {
+ Description: "Port to listen on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "port": {
+ Description: "Port to listen on the vm",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 22,
+ },
+ },
+ },
+ },
+ "rdp": {
+ Description: "RDP configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "connect_on": {
+ Description: "Port to listen on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "port": {
+ Description: "Port to listen on the vm",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 3389,
+ },
+ },
+ },
+ },
+ "forward_rule": {
+ Description: "Additional tcp forwarding rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "connect_on": {
+ Description: "Port to listen on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "port": {
+ Description: "Port to listen on the vm",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "depends": {
+ Description: "Dependent rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "rule_id": {
+ Description: "Rule id of the dependent rule",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ "delay_in_sec": {
+ Description: "Number of seconds the rule should wait after warming up the dependent rule",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 5,
+ },
+ },
+ },
+ },
+ },
+ }
+
+ return resource
+}
+
+func resourceVMRuleCreateOrUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)
+ saveServiceRequestV2 := buildASRule(d, Instance, c.AccountId)
+ return resourceASRuleCreateOrUpdate(ctx, d, meta, saveServiceRequestV2)
+}
diff --git a/internal/service/platform/autostopping/rule/as_vm_data_source.go b/internal/service/platform/autostopping/rule/as_vm_data_source.go
new file mode 100644
index 000000000..146773894
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_vm_data_source.go
@@ -0,0 +1,284 @@
+package as_rule
+
+import (
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func DataSourceVMRule() *schema.Resource {
+ resource := &schema.Resource{
+ Description: "Data source for retrieving a Harness Variable.",
+
+ ReadContext: resourceASRuleRead,
+
+ Schema: map[string]*schema.Schema{
+ "identifier": {
+ Description: "Unique identifier of the resource",
+ Type: schema.TypeFloat,
+ Computed: true,
+ },
+ "name": {
+ Description: "Name of the rule",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "cloud_connector_id": {
+ Description: "Id of the cloud connector",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "idle_time_mins": {
+ Description: "Idle time in minutes. This is the time that the AutoStopping rule waits before stopping the idle instances.",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 15,
+ },
+ "use_spot": {
+ Description: "Boolean that indicates whether the selected instances should be converted to spot vm",
+ Type: schema.TypeBool,
+ Default: false,
+ Optional: true,
+ },
+ "custom_domains": {
+ Description: "Custom URLs used to access the instances",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "filter": {
+ Type: schema.TypeList,
+ Required: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "vm_ids": {
+ Description: "Ids of instances that needs to be managed using the AutoStopping rules",
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "tags": {
+ Description: "Tags of instances that needs to be managed using the AutoStopping rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "key": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "value": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ },
+ },
+ },
+ "regions": {
+ Description: "Regions of instances that needs to be managed using the AutoStopping rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "zones": {
+ Description: "Zones of instances that needs to be managed using the AutoStopping rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ },
+ },
+ },
+ "http": {
+ Description: "Http routing configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "proxy_id": {
+ Description: "Id of the proxy",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "routing": {
+ Description: "Routing configuration used to access the instances",
+ Type: schema.TypeList,
+ MinItems: 1,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "source_protocol": {
+ Description: "Source protocol of the proxy can be http or https",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "target_protocol": {
+ Description: "Target protocol of the instance can be http or https",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "source_port": {
+ Description: "Port on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "target_port": {
+ Description: "Port on the VM",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "action": {
+ Description: "Organization Identifier for the Entity",
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ },
+ },
+ },
+ "health": {
+ Description: "Health Check Details",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "protocol": {
+ Description: "Protocol can be http or https",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "port": {
+ Description: "Health check port on the VM",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ "path": {
+ Description: "API path to use for health check",
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "timeout": {
+ Description: "Health check timeout",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "status_code_from": {
+ Description: "Lower limit for acceptable status code",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "status_code_to": {
+ Description: "Upper limit for acceptable status code",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "tcp": {
+ Description: "TCP routing configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "proxy_id": {
+ Description: "Id of the Proxy",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "ssh": {
+ Description: "SSH configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "connect_on": {
+ Description: "Port to listen on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "port": {
+ Description: "Port to listen on the vm",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 22,
+ },
+ },
+ },
+ },
+ "rdp": {
+ Description: "RDP configuration",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "connect_on": {
+ Description: "Port to listen on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "port": {
+ Description: "Port to listen on the vm",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 3389,
+ },
+ },
+ },
+ },
+ "forward_rule": {
+ Description: "Additional tcp forwarding rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "connect_on": {
+ Description: "Port to listen on the proxy",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "port": {
+ Description: "Port to listen on the vm",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "depends": {
+ Description: "Dependent rules",
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "rule_id": {
+ Description: "Rule id of the dependent rule",
+ Type: schema.TypeInt,
+ Required: true,
+ },
+ "delay_in_sec": {
+ Description: "Number of seconds the rule should wait after warming up the dependent rule",
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: 5,
+ },
+ },
+ },
+ },
+ },
+ }
+
+ return resource
+}
diff --git a/internal/service/platform/autostopping/rule/as_vm_test.go b/internal/service/platform/autostopping/rule/as_vm_test.go
new file mode 100644
index 000000000..a33164e25
--- /dev/null
+++ b/internal/service/platform/autostopping/rule/as_vm_test.go
@@ -0,0 +1,112 @@
+package as_rule_test
+
+import (
+ "fmt"
+ "strconv"
+ "testing"
+
+ "github.com/harness/harness-go-sdk/harness/nextgen"
+ "github.com/harness/terraform-provider-harness/internal/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+)
+
+func TestResourceVMRule(t *testing.T) {
+ name := "terraform-rule-test"
+ resourceName := "harness_autostopping_rule_vm.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProviderFactories: acctest.ProviderFactories,
+ // CheckDestroy: testRuleDestroy(resourceName),
+ Steps: []resource.TestStep{
+ {
+ Config: testVMRule(name),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "name", name),
+ ),
+ },
+ },
+ })
+}
+
+func testRuleDestroy(resourceName string) resource.TestCheckFunc {
+ return func(state *terraform.State) error {
+ rule, _ := testGetRule(resourceName, state)
+ if rule != nil {
+ return fmt.Errorf("Found vm rule: %d", rule.Id)
+ }
+ return nil
+ }
+}
+
+func testGetRule(resourceName string, state *terraform.State) (*nextgen.Service, error) {
+ r := acctest.TestAccGetResource(resourceName, state)
+ c, ctx := acctest.TestAccGetPlatformClientWithContext()
+ ruleId, err := strconv.ParseFloat(r.Primary.ID, 64)
+ if err != nil {
+ return nil, err
+ }
+ resp, _, err := c.CloudCostAutoStoppingRulesApi.AutoStoppingRuleDetails(ctx, c.AccountId, ruleId, c.AccountId)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return resp.Response.Service, nil
+}
+
+func testVMRule(name string) string {
+ return fmt.Sprintf(`
+ resource "harness_autostopping_rule_vm" "test" {
+ name = "%[1]s"
+ cloud_connector_id = "Azure_SE"
+ idle_time_mins = 10
+ filter {
+ vm_ids = ["/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Compute/virtualMachines/virtual_machine"]
+ regions = ["useast2"]
+ }
+ http {
+ proxy_id = "ap-chdpf8f83v0c1aj69oog"
+ routing {
+ source_protocol = "https"
+ target_protocol = "https"
+ source_port = 443
+ target_port = 443
+ action = "forward"
+ }
+ routing {
+ source_protocol = "http"
+ target_protocol = "http"
+ source_port = 80
+ target_port = 80
+ action = "forward"
+ }
+ health {
+ protocol = "http"
+ port = 80
+ path = "/"
+ timeout = 30
+ status_code_from = 200
+ status_code_to = 299
+ }
+ }
+ tcp {
+ proxy_id = "ap-chdpf8f83v0c1aj69oog"
+ ssh {
+ port = 22
+ }
+ rdp {
+ port = 3389
+ }
+ forward_rule {
+ port = 2233
+ }
+ }
+ depends {
+ rule_id = 24576
+ delay_in_sec = 5
+ }
+ }
+`, name)
+}