diff --git a/digitalocean/app/app_spec.go b/digitalocean/app/app_spec.go index 8197dd247..eb87f4607 100644 --- a/digitalocean/app/app_spec.go +++ b/digitalocean/app/app_spec.go @@ -263,7 +263,12 @@ func appSpecImageSourceSchema() map[string]*schema.Schema { "tag": { Type: schema.TypeString, Optional: true, - Description: "The repository tag. Defaults to latest if not provided.", + Description: "The repository tag. Defaults to latest if not provided. Cannot be specified if digest is provided.", + }, + "digest": { + Type: schema.TypeString, + Optional: true, + Description: "The image digest. Cannot be specified if tag is provided.", }, "deploy_on_push": { Type: schema.TypeList, @@ -765,12 +770,20 @@ func appSpecWorkerSchema() *schema.Resource { Optional: true, Description: "The amount of instances that this component should be scaled to.", }, +<<<<<<< HEAD "termination": { +======= + "autoscaling": { +>>>>>>> origin/main Type: schema.TypeList, Optional: true, MaxItems: 1, Elem: &schema.Resource{ +<<<<<<< HEAD Schema: appSpecTerminationSchema(workerComponent), +======= + Schema: appSpecAutoscalingSchema(), +>>>>>>> origin/main }, }, } @@ -1654,6 +1667,7 @@ func expandAppImageSourceSpec(config []interface{}) *godo.ImageSourceSpec { Registry: imageSourceConfig["registry"].(string), Repository: imageSourceConfig["repository"].(string), Tag: imageSourceConfig["tag"].(string), + Digest: imageSourceConfig["digest"].(string), RegistryCredentials: imageSourceConfig["registry_credentials"].(string), } @@ -1677,6 +1691,7 @@ func flattenAppImageSourceSpec(i *godo.ImageSourceSpec) []interface{} { r["registry"] = (*i).Registry r["repository"] = (*i).Repository r["tag"] = (*i).Tag + r["digest"] = (*i).Digest r["registry_credentials"] = (*i).RegistryCredentials if i.DeployOnPush != nil { @@ -2076,9 +2091,15 @@ func expandAppSpecWorkers(config []interface{}) []*godo.AppWorkerSpec { s.LogDestinations = expandAppLogDestinations(logDestinations) } +<<<<<<< HEAD termination := worker["termination"].([]interface{}) if len(termination) > 0 { s.Termination = expandAppTermination[godo.AppWorkerSpecTermination](termination) +======= + autoscaling := worker["autoscaling"].([]interface{}) + if len(autoscaling) > 0 { + s.Autoscaling = expandAppAutoscaling(autoscaling) +>>>>>>> origin/main } appWorkers = append(appWorkers, s) @@ -2109,6 +2130,7 @@ func flattenAppSpecWorkers(workers []*godo.AppWorkerSpec) []map[string]interface r["alert"] = flattenAppAlerts(w.Alerts) r["log_destination"] = flattenAppLogDestinations(w.LogDestinations) r["termination"] = flattenAppTermination(w.Termination) + r["autoscaling"] = flattenAppAutoscaling(w.Autoscaling) result[i] = r } diff --git a/digitalocean/app/resource_app_test.go b/digitalocean/app/resource_app_test.go index 5250350c3..54ab80473 100644 --- a/digitalocean/app/resource_app_test.go +++ b/digitalocean/app/resource_app_test.go @@ -1044,6 +1044,43 @@ func TestAccDigitalOceanApp_autoScale(t *testing.T) { "digitalocean_app.foobar", "spec.0.service.0.autoscaling.0.max_instance_count", "4"), resource.TestCheckResourceAttr( "digitalocean_app.foobar", "spec.0.service.0.autoscaling.0.metrics.0.cpu.0.percent", "60"), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.worker.0.name", "go-worker"), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.worker.0.autoscaling.0.min_instance_count", "1"), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.worker.0.autoscaling.0.max_instance_count", "2"), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.worker.0.autoscaling.0.metrics.0.cpu.0.percent", "80"), + ), + }, + }, + }) +} + +func TestAccDigitalOceanApp_ImageDigest(t *testing.T) { + var app godo.App + appName := acceptance.RandomTestName() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, + CheckDestroy: testAccCheckDigitalOceanAppDestroy, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccCheckDigitalOceanAppConfig_imageDigest, appName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanAppExists("digitalocean_app.foobar", &app), + resource.TestCheckResourceAttrSet("digitalocean_app.foobar", "live_url"), + resource.TestCheckResourceAttrSet("digitalocean_app.foobar", "live_domain"), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.service.0.image.0.registry_type", "DOCKER_HUB"), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.service.0.image.0.registry", "ubuntu"), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.service.0.image.0.repository", "nginx"), + resource.TestCheckResourceAttr( + "digitalocean_app.foobar", "spec.0.service.0.image.0.digest", "sha256:909169d4de5b750071dc2cbe286e18763f8ed23dd0f267b5db59ea33bdbf8853"), ), }, }, @@ -1260,6 +1297,29 @@ resource "digitalocean_app" "foobar" { } }` +var testAccCheckDigitalOceanAppConfig_imageDigest = ` +resource "digitalocean_app" "foobar" { + spec { + name = "%s" + region = "nyc" + + service { + name = "image-service" + instance_count = 1 + instance_size_slug = "apps-s-1vcpu-1gb" + + image { + registry_type = "DOCKER_HUB" + registry = "ubuntu" + repository = "nginx" + digest = "sha256:909169d4de5b750071dc2cbe286e18763f8ed23dd0f267b5db59ea33bdbf8853" + } + + http_port = 80 + } + } +}` + var testAccCheckDigitalOceanAppConfig_addInternalPort = ` resource "digitalocean_app" "foobar" { spec { @@ -1651,6 +1711,26 @@ resource "digitalocean_app" "foobar" { } } } + + worker { + name = "go-worker" + instance_size_slug = "apps-d-1vcpu-0.5gb" + + git { + repo_clone_url = "https://github.com/digitalocean/sample-sleeper.git" + branch = "main" + } + + autoscaling { + min_instance_count = 1 + max_instance_count = 2 + metrics { + cpu { + percent = 80 + } + } + } + } } }` diff --git a/docs/data-sources/app.md b/docs/data-sources/app.md index ca42e69d9..7822934a0 100644 --- a/docs/data-sources/app.md +++ b/docs/data-sources/app.md @@ -73,6 +73,7 @@ A `service` can contain: - `registry` - The registry name. Must be left empty for the `DOCR` registry type. Required for the `DOCKER_HUB` registry type. - `repository` - The repository name. - `tag` - The repository tag. Defaults to `latest` if not provided. + - `digest` - The image digest. Cannot be specified if `tag` is provided. - `deploy_on_push` - Configures automatically deploying images pushed to DOCR. - `enabled` - Whether to automatically deploy images pushed to DOCR. * `env` - Describes an environment variable made available to an app competent. @@ -173,6 +174,7 @@ A `worker` can contain: - `registry` - The registry name. Must be left empty for the `DOCR` registry type. Required for the `DOCKER_HUB` registry type. - `repository` - The repository name. - `tag` - The repository tag. Defaults to `latest` if not provided. + - `digest` - The image digest. Cannot be specified if `tag` is provided. - `deploy_on_push` - Configures automatically deploying images pushed to DOCR. - `enabled` - Whether to automatically deploy images pushed to DOCR. * `env` - Describes an environment variable made available to an app competent. @@ -198,6 +200,12 @@ A `worker` can contain: - `cluster_name` - The name of a DigitalOcean DBaaS OpenSearch cluster to use as a log forwarding destination. Cannot be specified if endpoint is also specified. * `termination` - Contains a component's termination parameters. - `grace_period_seconds` - The number of seconds to wait between sending a TERM signal to a container and issuing a KILL which causes immediate shutdown. Default: 120, Minimum 1, Maximum 600. +* `autoscaling` - Configuration for automatically scaling this component based on metrics. + - `min_instance_count` - The minimum amount of instances for this component. Must be less than max_instance_count. + - `max_instance_count` - The maximum amount of instances for this component. Must be more than min_instance_count. + - `metrics` - The metrics that the component is scaled on. + - `cpu` - Settings for scaling the component based on CPU utilization. + - `percent` - The average target CPU utilization for the component. A `job` can contain: @@ -230,6 +238,7 @@ A `job` can contain: - `registry` - The registry name. Must be left empty for the `DOCR` registry type. Required for the `DOCKER_HUB` registry type. - `repository` - The repository name. - `tag` - The repository tag. Defaults to `latest` if not provided. + - `digest` - The image digest. Cannot be specified if `tag` is provided. - `deploy_on_push` - Configures automatically deploying images pushed to DOCR. - `enabled` - Whether to automatically deploy images pushed to DOCR. * `env` - Describes an environment variable made available to an app competent. diff --git a/docs/resources/app.md b/docs/resources/app.md index 0d870503d..75f2bfcbb 100644 --- a/docs/resources/app.md +++ b/docs/resources/app.md @@ -269,6 +269,7 @@ A `service` can contain: - `repository` - The repository name. - `registry_credentials` - The credentials required to access a private Docker Hub or GitHub registry, in the following syntax `:`. - `tag` - The repository tag. Defaults to `latest` if not provided. + - `digest` - The image digest. Cannot be specified if `tag` is provided. - `deploy_on_push` - Configures automatically deploying images pushed to DOCR. - `enabled` - Whether to automatically deploy images pushed to DOCR. - `env` - Describes an environment variable made available to an app competent. @@ -379,6 +380,7 @@ A `worker` can contain: - `repository` - The repository name. - `registry_credentials` - The credentials required to access a private Docker Hub or GitHub registry, in the following syntax `:`. - `tag` - The repository tag. Defaults to `latest` if not provided. + - `digest` - The image digest. Cannot be specified if `tag` is provided. - `deploy_on_push` - Configures automatically deploying images pushed to DOCR. - `enabled` - Whether to automatically deploy images pushed to DOCR. - `env` - Describes an environment variable made available to an app competent. @@ -410,6 +412,12 @@ A `worker` can contain: - `cluster_name` - The name of a DigitalOcean DBaaS OpenSearch cluster to use as a log forwarding destination. Cannot be specified if endpoint is also specified. - `termination` - Contains a component's termination parameters. - `grace_period_seconds` - The number of seconds to wait between sending a TERM signal to a container and issuing a KILL which causes immediate shutdown. Default: 120, Minimum 1, Maximum 600. +- `autoscaling` - Configuration for automatically scaling this component based on metrics. + - `min_instance_count` - The minimum amount of instances for this component. Must be less than max_instance_count. + - `max_instance_count` - The maximum amount of instances for this component. Must be more than min_instance_count. + - `metrics` - The metrics that the component is scaled on. + - `cpu` - Settings for scaling the component based on CPU utilization. + - `percent` - The average target CPU utilization for the component. A `job` can contain: @@ -443,6 +451,7 @@ A `job` can contain: - `repository` - The repository name. - `registry_credentials` - The credentials required to access a private Docker Hub or GitHub registry, in the following syntax `:`. - `tag` - The repository tag. Defaults to `latest` if not provided. + - `digest` - The image digest. Cannot be specified if `tag` is provided. - `deploy_on_push` - Configures automatically deploying images pushed to DOCR. - `enabled` - Whether to automatically deploy images pushed to DOCR. - `env` - Describes an environment variable made available to an app competent.