cloudfoundry-community / terraform-provider-cloudfoundry

Terraform Cloud Foundry Provider
https://registry.terraform.io/providers/cloudfoundry-community/cloudfoundry/latest
Mozilla Public License 2.0
75 stars 87 forks source link

Error with cloudfoundry_app deployment: Start command not specified #553

Open pwalkr opened 9 months ago

pwalkr commented 9 months ago

It looks like the provider doesn't actually send command when deploying a cloudfoundry_app, despite plan showing the argument

$ terraform apply
data.archive_file.this: Reading...
data.archive_file.this: Read complete after 0s [id=74b890e8ddb9bcf3879780e3236535a4019ebba0]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated   
with the following symbols:
  + create

Terraform will perform the following actions:

  # cloudfoundry_app.this will be created
  + resource "cloudfoundry_app" "this" {
      + buildpack                       = (known after apply)
      + buildpacks                      = [
          + "python_buildpack",
        ]
      + command                         = "python main.py"
      + disk_quota                      = (known after apply)
      + enable_ssh                      = (known after apply)
      + environment                     = (sensitive value)
      + health_check_http_endpoint      = (known after apply)
      + health_check_invocation_timeout = (known after apply)
      + health_check_timeout            = (known after apply)
      + health_check_type               = "port"
      + id                              = (known after apply)
      + id_bg                           = (known after apply)
      + instances                       = 1
      + memory                          = (known after apply)
      + name                            = "start-test"
      + path                            = "app.zip"
      + ports                           = (known after apply)
      + source_code_hash                = "yRs6Xa632Dq6jCXUiOu9sKSo2Gce65Xrgzu4a7zcFFc="
      + space                           = "*******************"
      + stack                           = (known after apply)
      + stopped                         = false
      + strategy                        = "none"
      + timeout                         = 60
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

cloudfoundry_app.this: Creating...
cloudfoundry_app.this: Still creating... [10s elapsed]
cloudfoundry_app.this: Still creating... [20s elapsed]
cloudfoundry_app.this: Still creating... [30s elapsed]
cloudfoundry_app.this: Still creating... [40s elapsed]
cloudfoundry_app.this: Still creating... [50s elapsed]
╷
│ Error: Package staging failed: StagingError - Staging error: Start command not specified
│
│   with cloudfoundry_app.this,
│   on main.tf line 20, in resource "cloudfoundry_app" "this":
│   20: resource "cloudfoundry_app" "this" {
│
╵

Replicated using a basic python flask app and this terraform file:

terraform {
  required_providers {
    cloudfoundry = {
      source  = "cloudfoundry-community/cloudfoundry"
      version = "0.53.0"
    }
  }
}
provider "cloudfoundry" {
  api_url = "********************"
}
# app folder contains `main.py` and `requirements.txt`
data "archive_file" "this" {
  type        = "zip"
  source_dir  = "app"
  output_path = "app.zip"
}
resource "cloudfoundry_app" "this" {
  name       = "start-test"
  command    = "python main.py"
  buildpacks = ["python_buildpack"]

  space = "***************"

  path             = data.archive_file.this.output_path
  source_code_hash = data.archive_file.this.output_base64sha256
}

Contents of app/main.py and app/requirements.txt

import os
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

app.run(host = '0.0.0.0', port = os.environ['PORT'])
brotli==1.1.0
brotlicffi==1.1.0.0
chardet==5.2.0
cryptography==42.0.2
Flask==3.0.2
h2==4.1.0
js==1.0
mock==5.1.0
pyOpenSSL==24.0.0
simplejson==3.19.2
typing_extensions==4.9.0
zstandard==0.22.0

Other context:

$ terraform version
Terraform v1.3.2
$ cf api
API endpoint:   ****
API version:    3.121.0

I also tried to push the same app using this manifest.yml and it succeeds:

applications:
- name: 'start-test'
  command: python main.py
  path: app
  buildpacks:
    - python_buildpack
$ cf push -f manifest.yml
...
Instances starting...

name:              start-test
requested state:   started
routes:            *******************
last uploaded:     Wed 07 Feb 11:38:29 EST 2024
stack:             cflinuxfs3
buildpacks:
        name               version   detect output   buildpack name
        python_buildpack   1.8.11    python          python

type:            web
sidecars:
instances:       1/1
memory usage:    1024M
start command:   python main.py
pwalkr commented 9 months ago

Workaround: move the start command to Procfile (as recommended by app log "No start command specified by buildpack or via Procfile. App will not start unless a command is provided at runtime.")

The apply works with this change (git diff)

diff --git a/examples/app/app/Procfile b/examples/app/app/Procfile
new file mode 100644
index 0000000..629b83a
--- /dev/null
+++ b/app/Procfile
@@ -0,0 +1 @@
+web: python main.py

diff --git a/examples/app/main.tf b/examples/app/main.tf
index 5a88797..f24ccfb 100644
--- a/main.tf
+++ b/main.tf
@@ -19,7 +19,6 @@ data "archive_file" "this" {

 resource "cloudfoundry_app" "this" {
   name       = "start-test"
-  command    = "python main.py"
   buildpacks = ["python_buildpack"]