ionos-cloud / terraform-provider-ionoscloud

The IonosCloud Terraform provider gives the ability to deploy and configure resources using the IonosCloud APIs.
Mozilla Public License 2.0
34 stars 23 forks source link

"image_name" not mandatory for "plan" but for "apply" #24

Closed larsen0815 closed 3 years ago

larsen0815 commented 3 years ago

Description

"terraform plan" doesn't complain when a server resource doesn't contain "image_name" but fails to "apply" because of it missing.

Expected behavior

Environment

Terraform v1.0.0 on linux_amd64 provider registry.terraform.io/ionos-cloud/ionoscloud v5.1.7 Debian GNU/Linux 10 (buster)

Configuration Files

terraform {
  required_providers {
    ionoscloud = {
      source  = "ionos-cloud/ionoscloud"
    }
  }
}

provider "ionoscloud" {
  username = "${var.api_user}"
  password = "${var.api_password}"
  endpoint = "${var.api_endpoint}"
}

resource "ionoscloud_datacenter" "example" {
  name        = "example"
  location    = "de/fra"
}

resource "ionoscloud_lan" "LAN_10" {
  datacenter_id = ionoscloud_datacenter.example.id
  public        = true
}

resource "ionoscloud_ipblock" "SouthDakota" {
  location = "${ionoscloud_datacenter.example.location}"
  size     = 1
  name     = "SouthDakota" 
}

resource "ionoscloud_server" "SouthDakota" {
  name              = "SouthDakota Server"
  datacenter_id     = "${ionoscloud_datacenter.example.id}"
  cores             = 1
  ram               = 1024
  availability_zone = "AUTO"
  cpu_family        = "AMD_OPTERON"

  volume {
    name           = "SouthDakota HDD-Storage"
    size           = 20
    disk_type      = "HDD"
  }

  nic {
    lan             = "${ionoscloud_lan.LAN_10.id}"
    dhcp            = true
    ip              = "${ionoscloud_ipblock.SouthDakota.ips[0]}"
  }
}

How to Reproduce

I have imported a server from Nexinto. Adapted the main.tf to resemble the current state, so "plan" doesn't show any differences. Then I removed terraform.tfstate and switched the endpoint from Nexinto to Ionos to create this server on Ionos.

When I run "terraform plan", I get this:

# terraform plan
ionoscloud_datacenter.example: Refreshing state... [id=123]

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:

  # ionoscloud_ipblock.SouthDakota will be created
  + resource "ionoscloud_ipblock" "SouthDakota" {
      + id       = (known after apply)
      + ips      = (known after apply)
      + location = "de/fra"
      + name     = "SouthDakota"
      + size     = 1
    }

  # ionoscloud_lan.LAN_10 will be created
  + resource "ionoscloud_lan" "LAN_10" {
      + datacenter_id = "123"
      + id            = (known after apply)
      + public        = true
    }

  # ionoscloud_server.SouthDakota will be created
  + resource "ionoscloud_server" "SouthDakota" {
      + availability_zone = "AUTO"
      + boot_image        = (known after apply)
      + boot_volume       = (known after apply)
      + cores             = 1
      + cpu_family        = "AMD_OPTERON"
      + datacenter_id     = "123"
      + firewallrule_id   = (known after apply)
      + id                = (known after apply)
      + image_name        = (known after apply)
      + image_password    = (sensitive value)
      + name              = "SouthDakota Server"
      + primary_ip        = (known after apply)
      + primary_nic       = (known after apply)
      + ram               = 1024
      + ssh_key_path      = (known after apply)

      + nic {
          + dhcp = true
          + ip   = (known after apply)
          + ips  = (known after apply)
          + lan  = (known after apply)
          + mac  = (known after apply)
        }

      + volume {
          + availability_zone = (known after apply)
          + bus               = (known after apply)
          + disk_type         = "HDD"
          + image_aliases     = (known after apply)
          + licence_type      = (known after apply)
          + name              = "SouthDakota HDD-Storage"
          + size              = 20
        }
    }

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

Error and Debug Output

On "terraform apply":

ionoscloud_server.SouthDakota: Creating...
?
¦ Error: either 'image_name' or 'volume.0.image_name' must be provided
¦
¦   with ionoscloud_server.SouthDakota,
¦   on main.tf line 32, in resource "ionoscloud_server" "SouthDakota":
¦   32: resource "ionoscloud_server" "SouthDakota" {
¦
?

Additional Notes

Workaround:

mflorin commented 3 years ago

@larsen0815 - please try v5.2.0-beta.2 - please note this is a beta - since we've just upgraded the terraform sdk to v2.4.3

larsen0815 commented 3 years ago

Will test it within next week.

larsen0815 commented 3 years ago

Tested with v5.2.0 (not beta) after removing "image_name": Error: either 'image_name', 'licence_type', or 'image_alias' must be set "plan" show no error upfront.

larsen0815 commented 3 years ago

Using "image_name" as before, the plugin crashes:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x108b9ad]

goroutine 32 [running]:
github.com/ionos-cloud/terraform-provider-ionoscloud/ionoscloud.resourceDatacenterRead(0x17380e0, 0xc00058b080, 0xc00059ac00, 0x12f76e0, 0xc00058e1e0, 0xc00059f5f0, 0xc0000198f0, 0x40cbe8)
    github.com/ionos-cloud/terraform-provider-ionoscloud/ionoscloud/resource_datacenter.go:110 +0x25d
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).read(0xc0000c29c0, 0x1738060, 0xc000596640, 0xc00059ac00, 0x12f76e0, 0xc00058e1e0, 0x0, 0x0, 0x0)
    github.com/hashicorp/terraform-plugin-sdk/v2@v2.4.3/helper/schema/resource.go:297 +0x1ec
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).RefreshWithoutUpgrade(0xc0000c29c0, 0x1738060, 0xc000596640, 0xc000587b20, 0x12f76e0, 0xc00058e1e0, 0xc00000ecb8, 0x0, 0x0, 0x0)
    github.com/hashicorp/terraform-plugin-sdk/v2@v2.4.3/helper/schema/resource.go:564 +0x1c2
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).ReadResource(0xc0004cd100, 0x1738060, 0xc000596640, 0xc000596680, 0xc000596640, 0x1312600, 0x13707a0)
    github.com/hashicorp/terraform-plugin-sdk/v2@v2.4.3/helper/schema/grpc_provider.go:575 +0x42f
github.com/hashicorp/terraform-plugin-go/tfprotov5/server.(*server).ReadResource(0xc00017c160, 0x1738060, 0xc000596640, 0xc00058ab40, 0xc00017c160, 0xc0005626c0, 0xc000082ba0)
    github.com/hashicorp/terraform-plugin-go@v0.2.1/tfprotov5/server/server.go:298 +0x101
github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5._Provider_ReadResource_Handler(0x13707a0, 0xc00017c160, 0x1738120, 0xc0005626c0, 0xc00058aae0, 0x0, 0x1738120, 0xc0005626c0, 0xc0008a0300, 0x16b)
    github.com/hashicorp/terraform-plugin-go@v0.2.1/tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go:344 +0x217
google.golang.org/grpc.(*Server).processUnaryRPC(0xc00017bc00, 0x17460e0, 0xc00089f080, 0xc0001ca400, 0xc0004cb290, 0x2029e10, 0x0, 0x0, 0x0)
    google.golang.org/grpc@v1.32.0/server.go:1194 +0x50a
google.golang.org/grpc.(*Server).handleStream(0xc00017bc00, 0x17460e0, 0xc00089f080, 0xc0001ca400, 0x0)
    google.golang.org/grpc@v1.32.0/server.go:1517 +0xcfd
google.golang.org/grpc.(*Server).serveStreams.func1.2(0xc000034240, 0xc00017bc00, 0x17460e0, 0xc00089f080, 0xc0001ca400)
    google.golang.org/grpc@v1.32.0/server.go:859 +0xa1
created by google.golang.org/grpc.(*Server).serveStreams.func1
    google.golang.org/grpc@v1.32.0/server.go:857 +0x204
mflorin commented 3 years ago

Tested with v5.2.0 (not beta) after removing "image_name": Error: either 'image_name', 'licence_type', or 'image_alias' must be set "plan" show no error upfront.

yes, you need to specify licence_type OTHER or UNKNOWN if you're not using an image name

larsen0815 commented 3 years ago

Shouldn't "plan" already show a warning in that case?

larsen0815 commented 3 years ago

Regarding the crash mentioned before: Could be caused by the current DCD outage. Also received this when trying another time: The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ReadResource call. The plugin logs may contain more details. Maybe handle situations like this in the provider?

mflorin commented 3 years ago

Regarding the crash mentioned before: Could be caused by the current DCD outage. Also received this when trying another time: The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ReadResource call. The plugin logs may contain more details. Maybe handle situations like this in the provider?

if it's a crash than we definitely should avoid it, I'll look into it if I can manage to replicate the issue.

mflorin commented 3 years ago

Shouldn't "plan" already show a warning in that case?

Not necessarily. There are two issues here:

  1. plan usually reports syntax errors and attribute validation errors. Here this is not the case since either one of the three must be specified
  2. we can't tell in the provider whether we're in plan or apply phase - only terraform knows and orchestrates that

I'll look into how we can implement some custom validation (if possible) that would catch that in the plan phase.

larsen0815 commented 3 years ago

To replicate you could possibly use your HOSTS to redirect traffic to the endpoint to e.g. localhost.

DCD seems to be running again and the crash is gone. However, I have set licence_type = "OTHER" and still get the same warning either 'image_name', 'licence_type', or 'image_alias' must be set

mflorin commented 3 years ago

To replicate you could possibly use your HOSTS to redirect traffic to the endpoint to e.g. localhost.

DCD seems to be running again and the crash is gone. However, I have set licence_type = "OTHER" and still get the same warning either 'image_name', 'licence_type', or 'image_alias' must be set

can you paste here your plan?

larsen0815 commented 3 years ago

see "Configuration Files" above plus licence_type = "OTHER" (below resource "ionoscloud_server")

mflorin commented 3 years ago

you should specify the licence_type in the volume definition that's part of the server definition

larsen0815 commented 3 years ago

ok, will test with the next server that is up for migration (next week).

off-topic: Would it be possible to not start the VM when creating a new one?

mflorin commented 3 years ago

It's up to the api, afaik there's no option for that, I'll see if there's a workaround.

jbuchhammer commented 3 years ago

Yes, there is no option at the API. And if the API does not support this we should not workaround here at this level. The only way would be to create the sever, let it start and use API calls to stop it again which will be a hard stop and may cause more problems.

mflorin commented 3 years ago

agreed, I was thinking more in terms of a hidden, undocumented option of the api, if there's any :)

larsen0815 commented 3 years ago

Ok. Where should I open a ticket to ask for this feature in the API?

mflorin commented 3 years ago

that would be the vdc-bundles repo but I'm not sure if the guys are actually monitoring the github issues. We're using their internal Jira queue to report issues, on the VDC project

jbuchhammer commented 3 years ago

@larsen0815 : I'm not happy to say this, but I think the best way where you can keep track of this FR would be to write a mail to our support that Servers should allow for being created without starting in API and DCD. And please describe the use case behind it.

For the background: API and SDK/tooling are done by different teams. SDK/Tooling uses this public repo. The API team has no public repo - the API implementation is closed source. And it does also affect the DCD (another development team).

larsen0815 commented 3 years ago

you should specify the licence_type in the volume definition that's part of the server definition

Ok, this did work now. Thanks =)

Noticed another similar thing and a minor typo for which I am going to open separate tickets.