This is an automated email from the ASF dual-hosted git repository.

vishesh pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/cloudstack-terraform-provider.git


The following commit(s) were added to refs/heads/main by this push:
     new e62e4d4  Improves service offering resource (#64)
e62e4d4 is described below

commit e62e4d4905e37646b072e3c83e861d2a707ce11d
Author: Fábio Matavelli <[email protected]>
AuthorDate: Wed Mar 6 10:30:46 2024 +0000

    Improves service offering resource (#64)
---
 .github/workflows/testacc.yml                      |  88 +++++++++++++++
 README.md                                          |   2 +-
 cloudstack/resource_cloudstack_service_offering.go | 119 ++++++++++++++++++++-
 .../resource_cloudstack_service_offering_test.go   |  85 +++++++++++++++
 website/docs/r/service_offering.html.markdown      |  28 ++++-
 5 files changed, 315 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/testacc.yml b/.github/workflows/testacc.yml
new file mode 100644
index 0000000..fa364f8
--- /dev/null
+++ b/.github/workflows/testacc.yml
@@ -0,0 +1,88 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Acceptance Test
+
+on: [push, pull_request]
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number || 
github.ref }}-testacc
+  cancel-in-progress: true
+
+jobs:
+  testacc:
+    name: Acceptance Test
+    runs-on: ubuntu-22.04
+    env:
+      CLOUDSTACK_API_URL: http://localhost:8080/client/api
+    steps:
+      - uses: actions/checkout@v3
+      - name: Set up Go
+        uses: actions/setup-go@v3
+        with:
+          go-version: 1.19.x
+      - name: Wait Cloudstack to be ready
+        run: |
+          echo "Starting Cloudstack health check"
+          T=0
+          until [ $T -gt 20 ]  || curl -sfL http://localhost:8080 --output 
/dev/null
+          do
+            echo "Waiting for Cloudstack to be ready..."
+            ((T+=1))
+            sleep 30
+          done
+      - name: Setting up Cloudstack
+        run: |
+          docker exec $(docker container ls --format=json -l | jq -r .ID) 
python /root/tools/marvin/marvin/deployDataCenter.py -i 
/root/setup/dev/advanced.cfg
+          curl -sf --location "${CLOUDSTACK_API_URL}" \
+            --header 'Content-Type: application/x-www-form-urlencoded' \
+            --data-urlencode 'command=login' \
+            --data-urlencode 'username=admin' \
+            --data-urlencode 'password=password' \
+            --data-urlencode 'response=json' \
+            --data-urlencode 'domain=/' -j -c cookies.txt --output /dev/null
+
+          CLOUDSTACK_USER_ID=$(curl -fs 
"${CLOUDSTACK_API_URL}?command=listUsers&response=json" -b cookies.txt | jq -r 
'.listusersresponse.user[0].id')
+          CLOUDSTACK_API_KEY=$(curl -s 
"${CLOUDSTACK_API_URL}?command=getUserKeys&id=${CLOUDSTACK_USER_ID}&response=json"
 -b cookies.txt | jq -r '.getuserkeysresponse.userkeys.apikey')
+          CLOUDSTACK_SECRET_KEY=$(curl -fs 
"${CLOUDSTACK_API_URL}?command=getUserKeys&id=${CLOUDSTACK_USER_ID}&response=json"
 -b cookies.txt | jq -r '.getuserkeysresponse.userkeys.secretkey')
+
+          echo "::add-mask::$CLOUDSTACK_API_KEY"
+          echo "::add-mask::$CLOUDSTACK_SECRET_KEY"
+
+          echo "CLOUDSTACK_API_KEY=$CLOUDSTACK_API_KEY" >> $GITHUB_ENV
+          echo "CLOUDSTACK_SECRET_KEY=$CLOUDSTACK_SECRET_KEY" >> $GITHUB_ENV
+      - name: Install CMK
+        run: |
+          curl -sfL 
https://github.com/apache/cloudstack-cloudmonkey/releases/download/6.3.0/cmk.linux.x86-64
 -o /usr/local/bin/cmk
+          chmod +x /usr/local/bin/cmk
+      - name: Create extra resources
+        run: |
+          cmk -u $CLOUDSTACK_API_URL -k $CLOUDSTACK_API_KEY -s 
$CLOUDSTACK_SECRET_KEY -o json create project name=terraform 
displaytext=terraform
+      - name: Run acceptance test
+        run: |
+          make testacc
+    services:
+      cloudstack-simulator:
+        image: apache/cloudstack-simulator:${{ matrix.cloudstack_version }}
+        ports:
+          - 8080:5050
+    strategy:
+      matrix:
+        cloudstack_version:
+          - 4.17.2.0
+          - 4.18.1.0
+          - 4.19.0.0
diff --git a/README.md b/README.md
index 48846b9..3236f20 100644
--- a/README.md
+++ b/README.md
@@ -88,7 +88,7 @@ When Docker started the container you can go to 
http://localhost:8080/client and
 Once the login page is shown and you can login, you need to provision a 
simulated data-center:
 
 ```sh
-$ docker exec -ti cloudstack python 
/root/tools/marvin/marvin/deployDataCenter.py -i /root/setup/dev/advanced.cfg
+docker exec -it cloudstack-simulator python 
/root/tools/marvin/marvin/deployDataCenter.py -i /root/setup/dev/advanced.cfg
 ```
 
 If you refresh the client or login again, you will now get passed the initial 
welcome screen and be able to go to your account details and retrieve the API 
key and secret. Export those together with the URL:
diff --git a/cloudstack/resource_cloudstack_service_offering.go 
b/cloudstack/resource_cloudstack_service_offering.go
index ad887b1..25dad33 100644
--- a/cloudstack/resource_cloudstack_service_offering.go
+++ b/cloudstack/resource_cloudstack_service_offering.go
@@ -42,6 +42,61 @@ func resourceCloudStackServiceOffering() *schema.Resource {
                                Type:     schema.TypeString,
                                Required: true,
                        },
+                       "cpu_number": {
+                               Description: "Number of CPU cores",
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true,
+                       },
+                       "cpu_speed": {
+                               Description: "Speed of CPU in Mhz",
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true,
+                       },
+                       "host_tags": {
+                               Description: "The host tag for this service 
offering",
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                       },
+                       "limit_cpu_use": {
+                               Description: "Restrict the CPU usage to 
committed service offering",
+                               Type:        schema.TypeBool,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Default:     false,
+                       },
+                       "memory": {
+                               Description: "The total memory of the service 
offering in MB",
+                               Type:        schema.TypeInt,
+                               Optional:    true,
+                               ForceNew:    true,
+                       },
+                       "offer_ha": {
+                               Description: "The HA for the service offering",
+                               Type:        schema.TypeBool,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Default:     false,
+                       },
+                       "storage_type": {
+                               Description: "The storage type of the service 
offering. Values are local and shared",
+                               Type:        schema.TypeString,
+                               Optional:    true,
+                               ForceNew:    true,
+                               Default:     "shared",
+                               ValidateFunc: func(val interface{}, key string) 
(warns []string, errs []error) {
+                                       v := val.(string)
+
+                                       if v == "local" || v == "shared" {
+                                               return
+                                       }
+
+                                       errs = append(errs, fmt.Errorf("storage 
type should be either local or shared, got %s", v))
+
+                                       return
+                               },
+                       },
                },
        }
 }
@@ -53,6 +108,33 @@ func resourceCloudStackServiceOfferingCreate(d 
*schema.ResourceData, meta interf
 
        // Create a new parameter struct
        p := cs.ServiceOffering.NewCreateServiceOfferingParams(display_text, 
name)
+       if v, ok := d.GetOk("cpu_number"); ok {
+               p.SetCpunumber(v.(int))
+       }
+
+       if v, ok := d.GetOk("cpu_speed"); ok {
+               p.SetCpuspeed(v.(int))
+       }
+
+       if v, ok := d.GetOk("host_tags"); ok {
+               p.SetHosttags(v.(string))
+       }
+
+       if v, ok := d.GetOk("limit_cpu_use"); ok {
+               p.SetLimitcpuuse(v.(bool))
+       }
+
+       if v, ok := d.GetOk("memory"); ok {
+               p.SetMemory(v.(int))
+       }
+
+       if v, ok := d.GetOk("offer_ha"); ok {
+               p.SetOfferha(v.(bool))
+       }
+
+       if v, ok := d.GetOk("storage_type"); ok {
+               p.SetStoragetype(v.(string))
+       }
 
        log.Printf("[DEBUG] Creating Service Offering %s", name)
        s, err := cs.ServiceOffering.CreateServiceOffering(p)
@@ -84,8 +166,22 @@ func resourceCloudStackServiceOfferingRead(d 
*schema.ResourceData, meta interfac
        }
 
        d.SetId(s.Id)
-       d.Set("name", s.Name)
-       d.Set("display_text", s.Displaytext)
+
+       fields := map[string]interface{}{
+               "name":          s.Name,
+               "display_text":  s.Displaytext,
+               "cpu_number":    s.Cpunumber,
+               "cpu_speed":     s.Cpuspeed,
+               "host_tags":     s.Hosttags,
+               "limit_cpu_use": s.Limitcpuuse,
+               "memory":        s.Memory,
+               "offer_ha":      s.Offerha,
+               "storage_type":  s.Storagetype,
+       }
+
+       for k, v := range fields {
+               d.Set(k, v)
+       }
 
        return nil
 }
@@ -136,6 +232,25 @@ func resourceCloudStackServiceOfferingUpdate(d 
*schema.ResourceData, meta interf
                d.SetPartial("display_text")
        }
 
+       if d.HasChange("host_tags") {
+               log.Printf("[DEBUG] Host tags changed for %s, starting update", 
name)
+
+               // Create a new parameter struct
+               p := cs.ServiceOffering.NewUpdateServiceOfferingParams(d.Id())
+
+               // Set the new host tags
+               p.SetHosttags(d.Get("host_tags").(string))
+
+               // Update the host tags
+               _, err := cs.ServiceOffering.UpdateServiceOffering(p)
+               if err != nil {
+                       return fmt.Errorf(
+                               "Error updating the host tags for service 
offering %s: %s", name, err)
+               }
+
+               d.SetPartial("host_tags")
+       }
+
        d.Partial(false)
 
        return resourceCloudStackServiceOfferingRead(d, meta)
diff --git a/cloudstack/resource_cloudstack_service_offering_test.go 
b/cloudstack/resource_cloudstack_service_offering_test.go
new file mode 100644
index 0000000..1e1d6cc
--- /dev/null
+++ b/cloudstack/resource_cloudstack_service_offering_test.go
@@ -0,0 +1,85 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package cloudstack
+
+import (
+       "fmt"
+       "testing"
+
+       "github.com/apache/cloudstack-go/v2/cloudstack"
+       "github.com/hashicorp/terraform/helper/resource"
+       "github.com/hashicorp/terraform/terraform"
+)
+
+func TestAccCloudStackServiceOffering_basic(t *testing.T) {
+       var so cloudstack.ServiceOffering
+       resource.Test(t, resource.TestCase{
+               PreCheck:  func() { testAccPreCheck(t) },
+               Providers: testAccProviders,
+               Steps: []resource.TestStep{
+                       {
+                               Config: testAccCloudStackServiceOffering_basic,
+                               Check: resource.ComposeTestCheckFunc(
+                                       
testAccCheckCloudStackServiceOfferingExists("cloudstack_service_offering.test1",
 &so),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.test1", 
"cpu_number", "2"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.test1", 
"cpu_speed", "2200"),
+                                       
resource.TestCheckResourceAttr("cloudstack_service_offering.test1", "memory", 
"8096"),
+                               ),
+                       },
+               },
+       })
+}
+
+const testAccCloudStackServiceOffering_basic = `
+resource "cloudstack_service_offering" "test1" {
+  name                         = "service_offering_1"
+  display_text         = "Test"
+  cpu_number   = 2
+  cpu_speed            = 2200
+  memory        = 8096
+}
+`
+
+func testAccCheckCloudStackServiceOfferingExists(n string, so 
*cloudstack.ServiceOffering) resource.TestCheckFunc {
+       return func(s *terraform.State) error {
+               rs, ok := s.RootModule().Resources[n]
+               if !ok {
+                       return fmt.Errorf("Not found: %s", n)
+               }
+
+               if rs.Primary.ID == "" {
+                       return fmt.Errorf("No service offering ID is set")
+               }
+
+               cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
+               resp, _, err := 
cs.ServiceOffering.GetServiceOfferingByID(rs.Primary.ID)
+               if err != nil {
+                       return err
+               }
+
+               if resp.Id != rs.Primary.ID {
+                       return fmt.Errorf("Service offering not found")
+               }
+
+               *so = *resp
+
+               return nil
+       }
+}
diff --git a/website/docs/r/service_offering.html.markdown 
b/website/docs/r/service_offering.html.markdown
index c4b5096..94735eb 100644
--- a/website/docs/r/service_offering.html.markdown
+++ b/website/docs/r/service_offering.html.markdown
@@ -24,16 +24,36 @@ resource "cloudstack_service_offering" "example" {
 
 The following arguments are supported:
 
-* `name` - (Required) The name of the service offering.
-* `display_text` - (Required) The display text of the service offering.
+* `name` - (Required) Name of the service offering.
+    Changing this forces a new resource to be created.
+
+* `display_text` - (Optional) The display text of the service offering.
+
+* `cpu_number` - (Optional) The number of CPU cores.
+    Changing this forces a new resource to be created.
+
+* `cpu_speed` - (Optional) The speed of the CPU in Mhz.
+    Changing this forces a new resource to be created.
+
+* `memory` - (Optional) Memory reserved by the VM in MB.
+    Changing this forces a new resource to be created.
+
+* `host_tags` - (Optional) The host tags for the service offering.
+
+* `limit_cpu_use` - (Optional) Restrict the CPU usage to committed service 
offering.
+    Changing this forces a new resource to be created.
+
+* `offer_ha` - (Optional) The HA for the service offering.
+    Changing this forces a new resource to be created.
+
+* `storage_type` - (Optional) The storage type of the service offering. Values 
are `local` and `shared`.
+    Changing this forces a new resource to be created.
 
 ## Attributes Reference
 
 The following attributes are exported:
 
 * `id` - The ID of the service offering.
-* `name` - The name of the service offering.
-* `display_text` - The display text of the service offering.
 
 ## Import
 

Reply via email to