Skip to content

Commit

Permalink
Add servergroup policy and rules field support
Browse files Browse the repository at this point in the history
  • Loading branch information
Tjev committed May 31, 2022
1 parent a3458ea commit 9830dcd
Show file tree
Hide file tree
Showing 3 changed files with 300 additions and 9 deletions.
98 changes: 91 additions & 7 deletions openstack/resource_openstack_compute_servergroup_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"

"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
)
Expand Down Expand Up @@ -41,6 +42,29 @@ func resourceComputeServerGroupV2() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
},

"policy": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},

"rules": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"max_server_per_host": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
ValidateFunc: validation.IntAtLeast(1),
},
},
},
},

"members": {
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -68,12 +92,57 @@ func resourceComputeServerGroupV2Create(ctx context.Context, d *schema.ResourceD
rawPolicies := d.Get("policies").([]interface{})
policies := expandComputeServerGroupV2Policies(computeClient, rawPolicies)

createOpts := ComputeServerGroupV2CreateOpts{
servergroups.CreateOpts{
Name: name,
Policies: policies,
},
MapValueSpecs(d),
policy := d.Get("policy").(string)
rules_v, rules_set := d.GetOk("rules")

var createOpts ComputeServerGroupV2CreateOpts

// "policies" is replaced with "policy" and optional "rules" since microversion 2.64
if len(policies) > 0 {
if policy != "" {
return diag.Errorf("Cannot create with both \"policies\" and \"policy\" field specified")
}
if rules_set {
return diag.Errorf("Cannot use \"policies\" field with \"rules\"" +
" - omit the \"rules\" or use \"policy\" instead")
}
createOpts = ComputeServerGroupV2CreateOpts{
servergroups.CreateOpts{
Name: name,
Policies: policies,
},
MapValueSpecs(d),
}
} else {
computeClient.Microversion = "2.64"

if policy == "anti-affinity" && rules_set {
rules := rules_v.([]map[string]interface{})

var max_server_per_host int
if v, ok := rules[0]["max_server_per_host"]; ok {
max_server_per_host = v.(int)
}

createOpts = ComputeServerGroupV2CreateOpts{
servergroups.CreateOpts{
Name: name,
Policy: policy,
Rules: &servergroups.Rules{
MaxServerPerHost: max_server_per_host,
},
},
MapValueSpecs(d),
}
} else {
createOpts = ComputeServerGroupV2CreateOpts{
servergroups.CreateOpts{
Name: name,
Policy: policy,
},
MapValueSpecs(d),
}
}
}

log.Printf("[DEBUG] openstack_compute_servergroup_v2 create options: %#v", createOpts)
Expand Down Expand Up @@ -102,11 +171,26 @@ func resourceComputeServerGroupV2Read(_ context.Context, d *schema.ResourceData,
log.Printf("[DEBUG] Retrieved openstack_compute_servergroup_v2 %s: %#v", d.Id(), sg)

d.Set("name", sg.Name)
d.Set("policies", sg.Policies)

if len(sg.Policies) > 0 {
d.Set("policy", sg.Policies)
}

d.Set("members", sg.Members)

d.Set("region", GetRegion(d, config))

if sg.Policy != nil {
d.Set("policy", sg.Policy)
}

if sg.Rules != nil {
rules := make(map[string]interface{})
rules["max_server_per_host"] = sg.Rules.MaxServerPerHost
rules_l := []map[string]interface{}{rules}
d.Set("rules", rules_l)
}

return nil
}

Expand Down
183 changes: 183 additions & 0 deletions openstack/resource_openstack_compute_servergroup_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package openstack

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand Down Expand Up @@ -36,6 +37,112 @@ func TestAccComputeV2ServerGroup_basic(t *testing.T) {
})
}

func TestAccComputeV2ServerGroup_basic_v2_64(t *testing.T) {
var sg servergroups.ServerGroup

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckNonAdminOnly(t)
},
ProviderFactories: testAccProviders,
CheckDestroy: testAccCheckComputeV2ServerGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeV2ServerGroupV264Policy,
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeV2ServerGroupExists("openstack_compute_servergroup_v2.sg_1", &sg),
resource.TestCheckResourceAttr(
"openstack_compute_servergroup_v2.sg_1", "policy", "affinity"),
),
},
},
})
}

func TestAccComputeV2ServerGroup_v2_64_anti_affinity(t *testing.T) {
var sg servergroups.ServerGroup

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckNonAdminOnly(t)
},
ProviderFactories: testAccProviders,
CheckDestroy: testAccCheckComputeV2ServerGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeV2ServerGroupV264PolicyAntiAffinity,
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeV2ServerGroupExists("openstack_compute_servergroup_v2.sg_1", &sg),
resource.TestCheckResourceAttr(
"openstack_compute_servergroup_v2.sg_1", "policy", "anti-affinity"),
),
},
},
})
}

func TestAccComputeV2ServerGroup_v2_64_with_rules(t *testing.T) {
var sg servergroups.ServerGroup

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckNonAdminOnly(t)
},
ProviderFactories: testAccProviders,
CheckDestroy: testAccCheckComputeV2ServerGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeV2ServerGroupV264PolicyRules,
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeV2ServerGroupExists("openstack_compute_servergroup_v2.sg_1", &sg),
resource.TestCheckResourceAttr(
"openstack_compute_servergroup_v2.sg_1", "policy", "anti-affinity"),
resource.TestCheckResourceAttr(
"openstack_compute_servergroup_v2.sg_1", "rules.max_server_per_host", "2"),
),
},
},
})
}

func TestAccComputeV2ServerGroup_v2_64_with_invalid_rules(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckNonAdminOnly(t)
},
ProviderFactories: testAccProviders,
CheckDestroy: testAccCheckComputeV2ServerGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeV2ServerGroupV264PolicyRules,
ExpectError: regexp.MustCompile(`expected max_server_per_host to be at least 1, got .*`),
},
},
})
}

func TestAccComputeV2ServerGroup_policies_and_policy(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckNonAdminOnly(t)
},
ProviderFactories: testAccProviders,
CheckDestroy: testAccCheckComputeV2ServerGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeV2ServerGroupV264Policy,
ExpectError: regexp.MustCompile(
"Cannot create with both \"policies\" and \"policy\" field specified"),
},
},
})
}

func TestAccComputeV2ServerGroup_affinity(t *testing.T) {
var instance servers.Server
var sg servergroups.ServerGroup
Expand Down Expand Up @@ -64,6 +171,32 @@ func TestAccComputeV2ServerGroup_affinity(t *testing.T) {
})
}

func TestAccComputeV2ServerGroup_affinity_v2_64(t *testing.T) {
var instance servers.Server
var sg servergroups.ServerGroup

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckNonAdminOnly(t)
},
ProviderFactories: testAccProviders,
CheckDestroy: testAccCheckComputeV2ServerGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeV2ServerGroupAffinityV264(),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeV2ServerGroupExists("openstack_compute_servergroup_v2.sg_1", &sg),
testAccCheckComputeV2InstanceExists("openstack_compute_instance_v2.instance_1", &instance),
testAccCheckComputeV2InstanceInServerGroup(&instance, &sg),
resource.TestCheckResourceAttr(
"openstack_compute_servergroup_v2.sg_1", "policy", "affinity"),
),
},
},
})
}

func TestAccComputeV2ServerGroup_soft_affinity(t *testing.T) {
var instance servers.Server
var sg servergroups.ServerGroup
Expand Down Expand Up @@ -166,6 +299,36 @@ resource "openstack_compute_servergroup_v2" "sg_1" {
}
`

const testAccComputeV2ServerGroupV264Policy = `
resource "openstack_compute_servergroup_v2" "sg_1" {
name = "sg_1"
policy = "affinity"
`

const testAccComputeV2ServerGroupV264PolicyAntiAffinity = `
resource "openstack_compute_servergroup_v2" "sg_1" {
name = "sg_1"
policy = "anti-affinity"
`

const testAccComputeV2ServerGroupV264PolicyRules = `
resource "openstack_compute_servergroup_v2" "sg_1" {
name = "sg_1"
policy = "anti-affinity"
rules = {
max_server_per_host = 2
}
`

const testAccComputeV2ServerGroupV264InvalidPolicyRules = `
resource "openstack_compute_servergroup_v2" "sg_1" {
name = "sg_1"
policy = "anti-affinity"
rules = {
max_server_per_host = -1
}
`

func testAccComputeV2ServerGroupAffinity() string {
return fmt.Sprintf(`
resource "openstack_compute_servergroup_v2" "sg_1" {
Expand Down Expand Up @@ -205,3 +368,23 @@ resource "openstack_compute_instance_v2" "instance_1" {
}
`, osNetworkID)
}

func testAccComputeV2ServerGroupAffinityV264() string {
return fmt.Sprintf(`
resource "openstack_compute_servergroup_v2" "sg_1" {
name = "sg_1"
policy = "affinity"
}
resource "openstack_compute_instance_v2" "instance_1" {
name = "instance_1"
security_groups = ["default"]
scheduler_hints {
group = "${openstack_compute_servergroup_v2.sg_1.id}"
}
network {
uuid = "%s"
}
}
`, osNetworkID)
}

0 comments on commit 9830dcd

Please sign in to comment.