Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

service offering. sdk framework rewrite #138

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Conversation

poddm
Copy link
Contributor

@poddm poddm commented Oct 21, 2024

Enhanced the following resources to support the full api spec.

  • cloudstack_service_offering_constrained
  • cloudstack_service_offering_unconstrained
  • cloudstack_service_offering_fixed

I split the service offering API up into multiple resources to make it a bit clearer of the different qos types

@CodeBleu
Copy link
Collaborator

@poddm Can you add the updated docs to this PR as well? I believe you had docs on the other PR you closed, but there doesn't appear to be updated docs for this.

I have pulled down your branch to test, and am still having issues with needing to specify the domain or domainid.

I get the following error:

│ Error: Error creating service offering
│
│   with cloudstack_service_offering_fixed.standard_offering["8-8"],
│   on service_offerings.tf line 21, in resource "cloudstack_service_offering_fixed" "standard_offering":
│   21: resource "cloudstack_service_offering_fixed" "standard_offering" {
│
│ Could not create fixed offering, unexpected error: CloudStack API error 431 (CSExceptionErrorCode: 9999): Unable to execute API command createserviceoffering due to invalid value. Invalid parameter domainid value="79151a13-70ff-4ddc-918e-8d8deab2c289" due to incorrect
│ long value format, or entity does not exist or due to incorrect parameter annotation for the field in api cmd class.

I'm using it like this:

resource "cloudstack_service_offering_fixed" "standard_offering" {
  for_each = local.cpu_ram_map

  name         = "ACE-${each.value.cpu}C${each.value.cpu}-${each.value.ram}R${each.value.ram}-S"
  domain_ids  = [local.domain_id]
  display_text = "ACE-${each.value.cpu}C${each.value.cpu}-${each.value.ram}R${each.value.ram}-S"
  cpu_number   = each.value.cpu
  cpu_speed    = var.standard_cpu_speed
  host_tags    = "standard"
  storage_tags = "standard_storage"
  memory       = each.value.ram * 1024 # Convert GB to MB
  offer_ha     = false
}

my locals

locals {
  cpus = [1, 2, 4, 8, 16, 32, 64]
  rams = [1, 2, 4, 8, 24, 32, 40, 48, 56, 64, 128]

  cpu_ram_combinations = flatten([
    for cpu in local.cpus : [
      for ram in local.rams : {
        cpu = cpu
        ram = ram
      }
    ]
  ])
  # Create a map for for_each
  cpu_ram_map = {
    for combination in local.cpu_ram_combinations :
    "${combination.cpu}-${combination.ram}" => combination
  }
  domain_id = "79151a13-70ff-4ddc-918e-8d8deab2c289"
}

@CodeBleu CodeBleu added this to the v0.6.0 milestone Oct 22, 2024
@poddm poddm changed the title sdk framework rewrite service offering. sdk framework rewrite Oct 24, 2024
@poddm
Copy link
Contributor Author

poddm commented Oct 25, 2024

@CodeBleu , I fixed the domain ids issue. Try now.

Also, regarding the documentation. I was looking at using the generator but it might be better to scope all that work to its own PR. https://github.com/hashicorp/terraform-plugin-docs

@CodeBleu
Copy link
Collaborator

CodeBleu commented Oct 25, 2024

@CodeBleu , I fixed the domain ids issue. Try now.

Also, regarding the documentation. I was looking at using the generator but it might be better to scope all that work to its own PR. https://github.com/hashicorp/terraform-plugin-docs

@poddm Thanks!!
I was able to successfully add offering with specifying the UUID for domain_ids in an list, but I have a couple of questions.

  1. Can this also be added with putting the name "ACE" or "/ROOT/ACE" and it automatically get the correct UUID?
  2. I need to specify the storage_type as well, but I need to be able to do this without having to specify a disk_offering Is this feasable? Right now without specifying the disk_offering it defaults to shared, and I'd like to be able to change this to local without having to specify a full disk_offering.

I just did a disk_offering and it applied, however it still shows shared instead of local like I have selected.

-/+ resource "cloudstack_service_offering_fixed" "standard_offering" {
      + disk_offering           = {
          + cache_mode               = "none" # forces replacement
          + disk_offering_strictness = false # forces replacement
          + provisioning_type        = "thin" # forces replacement
          + root_disk_size           = 0 # forces replacement
          + storage_type             = "local" # forces replacement
        }
      ~ id                      = "16ee216c-eba1-4dc0-ab96-5bc6513c6616" -> (known after apply)
        name                    = "ACE-8C8-8R8-S"
        # (11 unchanged attributes hidden)
    }

you can see above that the tags is not shown there

{
  "format_version": "1.0",
  "terraform_version": "1.8.1",
  "values": {
    "root_module": {
      "resources": [
        {
          "address": "cloudstack_service_offering_fixed.standard_offering[\"8-8\"]",
          "mode": "managed",
          "type": "cloudstack_service_offering_fixed",
          "name": "standard_offering",
          "index": "8-8",
          "provider_name": "registry.opentofu.org/cloudstack/cloudstack",
          "schema_version": 0,
          "values": {
            "cpu_number": 8,
            "cpu_speed": 2400,
            "deployment_planner": null,
            "disk_hypervisor": null,
            "disk_offering": {
              "cache_mode": "none",
              "disk_offering_strictness": false,
              "provisioning_type": "thin",
              "root_disk_size": 0,
              "storage_type": "local"
            },
            "disk_offering_id": null,
            "disk_storage": null,
            "display_text": "ACE-8C8-8R8-S",
            "domain_ids": [
              "79151a13-70ff-4ddc-918e-8d8deab2c289"
            ],
            "dynamic_scaling_enabled": false,
            "host_tags": "standard",
            "id": "b7945e90-5432-4a87-b8f8-0711576ed75c",
            "is_volatile": false,
            "limit_cpu_use": false,
            "memory": 8192,
            "name": "ACE-8C8-8R8-S",
            "network_rate": null,
            "offer_ha": false,
            "storage_tags": "standard_storage",
            "zone_ids": null
          },
          "sensitive_values": {
            "disk_offering": {},
            "domain_ids": [
              false
            ]
          }
        }
      ]
    }
  }
}

Also, why is storage_tags avail in both at the 'root' level of the resource and also as tags in the disk_offerings?

resource "cloudstack_service_offering_fixed" "standard_offering" {
  for_each = local.cpu_ram_map

  name                     = "ACE-${each.value.cpu}C${each.value.cpu}-${each.value.ram}R${each.value.ram}-S"
  domain_ids               = [local.domain_id]
  display_text             = "ACE-${each.value.cpu}C${each.value.cpu}-${each.value.ram}R${each.value.ram}-S"
  cpu_number               = each.value.cpu
  cpu_speed                = var.standard_cpu_speed
  host_tags                = "standard"
  storage_tags             = "standard_storage"
  memory                   = each.value.ram * 1024 # Convert GB to MB
  offer_ha                 = false
  disk_offering            =  {
    storage_type             = "local"
    provisioning_type        = "thin"
    cache_mode               = "none"
    root_disk_size           = 0
    tags                     = "standard_storage"
    disk_offering_strictness = false
  }
}

image

@poddm
Copy link
Contributor Author

poddm commented Oct 25, 2024

Can this also be added with putting the name "ACE" or "/ROOT/ACE" and it automatically get the correct UUID?

I think it would be better to add a data resource for domains. The problem I see with this approach is the resource will never become tainted if it was recreated as the same name. Subsequent resources that may modify or depend on the domain would never detect the newly re/created domain.

ex.

data "cloudstack_domain" "ace" {
    name = "/ROOT/ACE" 
}

resource "cloudstack_service_offering_fixed" "standard_offering" {
  ...
  domain_ids = [data.cloudstack_domain.ace.id]
}

I need to specify the storage_type as well, but I need to be able to do this without having to specify a disk_offering Is this feasable? Right now without specifying the disk_offering it defaults to shared, and I'd like to be able to change this to local without having to specify a full disk_offering.

Let me check. I believe storage_type is only applicable when creating a "compute only disk offering"/disk_offering block.

Also, why is storage_tags avail in both at the 'root' level of the resource and also as tags in the disk_offerings?

Thats a bug. storage tags should be in the disk_offering block

@CodeBleu
Copy link
Collaborator

@poddm Thank you so much for looking into this.

Once this offering stuff is complete, I still need a way to implement this with the cloudstack_instance resource. If I specify an offering that is constrained/dynamic, I need a way in the cloudstack_instance resource to specify the min/max of the CPU, Mem..etc. Otherwise right now it will just fail saying that it's missing values I'm not able to provide currently, and I can't use it.

Is this something you can fix with a new PR for cloudstack_instance

@vishesh92
Copy link
Member

@poddm I haven' tested but PR looks good. Left some minor comments.

@poddm
Copy link
Contributor Author

poddm commented Oct 28, 2024

@poddm Thank you so much for looking into this.

Once this offering stuff is complete, I still need a way to implement this with the cloudstack_instance resource. If I specify an offering that is constrained/dynamic, I need a way in the cloudstack_instance resource to specify the min/max of the CPU, Mem..etc. Otherwise right now it will just fail saying that it's missing values I'm not able to provide currently, and I can't use it.

Is this something you can fix with a new PR for cloudstack_instance

You can provide the values in the details field.

resource "cloudstack_instance" "this" {
    name = cloud
    display_name  = "cloud details"
    details = {cpuNumber = "4", memory = "2048"}
}

@CodeBleu
Copy link
Collaborator

CodeBleu commented Oct 28, 2024

@poddm Thank you so much for looking into this.
Once this offering stuff is complete, I still need a way to implement this with the cloudstack_instance resource. If I specify an offering that is constrained/dynamic, I need a way in the cloudstack_instance resource to specify the min/max of the CPU, Mem..etc. Otherwise right now it will just fail saying that it's missing values I'm not able to provide currently, and I can't use it.
Is this something you can fix with a new PR for cloudstack_instance

You can provide the values in the details field.

resource "cloudstack_instance" "this" {
    name = cloud
    display_name  = "cloud details"
    details = {cpuNumber = "4", memory = "2048"}
}

@poddm This is not currently part of the provider. Do you have this in your own branch? If so, Is there a PR for this too?

https://registry.terraform.io/providers/cloudstack/cloudstack/latest/docs/resources/instance

I tried to use what you show anyway, and I get this:

cloudstack_instance.test_box[0]: Creating...
╷
│ Error: Error creating the new instance ace-test-box-0: invalid character '<' looking for beginning of value
│
│   with cloudstack_instance.test_box[0],
│   on main.tf line 46, in resource "cloudstack_instance" "test_box":
│   46: resource "cloudstack_instance" "test_box" {
│
╵

  # cloudstack_instance.test_box[0] will be created
  + resource "cloudstack_instance" "test_box" {
      + details          = {
          + "cpuNumber" = "8"
          + "memory"    = "4096"
        }

@CodeBleu
Copy link
Collaborator

@poddm Not sure if you saw that I'm still having issues with this or not. Wondering what I need to do?
#138 (comment)

…to null, moved storage_tags field to nested block disk_offering
@poddm
Copy link
Contributor Author

poddm commented Oct 30, 2024

@CodeBleu ,

I need to specify the storage_type as well, but I need to be able to do this without having to specify a disk_offering Is this feasable? Right now without specifying the disk_offering it defaults to shared, and I'd like to be able to change this to local without having to specify a full disk_offering.

I fixed the duplicate storage_offering field.

Error: Error creating the new instance ace-test-box-0: invalid character '<' looking for beginning of value

This usually means the management server api returned an html error response and not json like the client library is expecting. I've been using this in 0.4.0 release.

@CodeBleu
Copy link
Collaborator

@poddm

I fixed the duplicate storage_offering field.

Thanks, I will test this later. My main issue was the storage_type would not change to what I selected. It defaults to shared and I wanted local. This is mentioned above in big comment, so maybe that part got lost.

image

Error: Error creating the new instance ace-test-box-0: invalid character '<' looking for beginning of value

This usually means the management server api returned an html error response and not json like the client library is expecting. I've been using this in 0.4.0 release.

What should I do?

  1. I don't even see the details part of cloudstack_instance even documented.
  2. I went ahead and used what you said to use, but I get that error whenever I add the details part

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants