Skip to content

Commit

Permalink
Merge branch 'master' into f-scaling-policy-data-source
Browse files Browse the repository at this point in the history
  • Loading branch information
lgfa29 committed Oct 30, 2020
2 parents 7ab6d50 + e0ae17b commit b731ef4
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 0 deletions.
1 change: 1 addition & 0 deletions nomad/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func Provider() terraform.ResourceProvider {
"nomad_quota_specification": resourceQuotaSpecification(),
"nomad_sentinel_policy": resourceSentinelPolicy(),
"nomad_volume": resourceVolume(),
"nomad_scheduler_config": resourceSchedulerConfig(),
},
}
}
Expand Down
135 changes: 135 additions & 0 deletions nomad/resource_scheduler_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package nomad

import (
"errors"
"fmt"
"log"

"github.com/hashicorp/nomad/api"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)

func resourceSchedulerConfig() *schema.Resource {
return &schema.Resource{
Create: resourceSchedulerConfigurationCreate,
Update: resourceSchedulerConfigurationCreate,
Delete: resourceSchedulerConfigurationDelete,
Read: resourceSchedulerConfigurationRead,

Schema: map[string]*schema.Schema{
"scheduler_algorithm": {
Description: "Specifies whether scheduler binpacks or spreads allocations on available nodes.",
Type: schema.TypeString,
Default: "binpack",
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"binpack",
"spread",
}, false),
},
},
// TODO(jrasell) once the Terraform SDK has been updated within
// this provider, we should add validation.MapKeyMatch to this
// schema entry using a regex such as:
// "("^[service,system,batch]_scheduler_enabled")".
"preemption_config": {
Description: "Options to enable preemption for various schedulers.",
Optional: true,
Type: schema.TypeMap,
Elem: &schema.Schema{
Type: schema.TypeBool,
},
},
},
}
}

func resourceSchedulerConfigurationCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(ProviderConfig).client
operator := client.Operator()

config := api.SchedulerConfiguration{
SchedulerAlgorithm: api.SchedulerAlgorithm(d.Get("scheduler_algorithm").(string)),
PreemptionConfig: api.PreemptionConfig{},
}

// Unpack the preemption block.
preempt, ok := d.GetOk("preemption_config")
if ok {
preemptMap, ok := preempt.(map[string]interface{})
if !ok {
return errors.New("failed to unpack preemption configuration block")
}

if val, ok := preemptMap["batch_scheduler_enabled"].(bool); ok {
config.PreemptionConfig.BatchSchedulerEnabled = val
}
if val, ok := preemptMap["service_scheduler_enabled"].(bool); ok {
config.PreemptionConfig.ServiceSchedulerEnabled = val
}
if val, ok := preemptMap["system_scheduler_enabled"].(bool); ok {
config.PreemptionConfig.SystemSchedulerEnabled = val
}
}

// Perform the config write.
log.Printf("[DEBUG] Upserting Scheduler configuration")
if _, _, err := operator.SchedulerSetConfiguration(&config, nil); err != nil {
return fmt.Errorf("error upserting scheduler configuration: %s", err.Error())
}
log.Printf("[DEBUG] Upserted scheduler configuration")

return resourceSchedulerConfigurationRead(d, meta)
}

// resourceSchedulerConfigurationDelete does not do anything:
//
// There is not a correct way to destroy this "resource" nor check it was
// destroyed.
//
// Consider the following:
// 1. an operator manually updates the Nomad scheduler config, or doesn't
// 2. they decide to move management over to Terraform
// 3. they get rid of Terraform management
//
// If the destroy reverts to the Nomad default configuration, we are over
// writing changes based on assumption. We cannot go back in time to the
// initial version as we do not have this information available, so we just
// have to leave it be.
func resourceSchedulerConfigurationDelete(_ *schema.ResourceData, _ interface{}) error { return nil }

func resourceSchedulerConfigurationRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(ProviderConfig).client
operator := client.Operator()

// The scheduler config doesn't have a UUID, so the resource uses the agent
// region. Grab this so we can set it later.
reg, err := client.Agent().Region()
if err != nil {
return fmt.Errorf("error getting region: %s", err.Error())
}
// retrieve the config
log.Printf("[DEBUG] Reading scheduler configuration")
config, _, err := operator.SchedulerGetConfiguration(nil)
if err != nil {
return fmt.Errorf("error reading scheduler configuration: %s", err.Error())
}
log.Printf("[DEBUG] Read scheduler configuration")

d.SetId(fmt.Sprintf("nomad-scheduler-configuration-%s", reg))

// Set the algorithm, handling any error when performing the set.
if err := d.Set("scheduler_algorithm", config.SchedulerConfig.SchedulerAlgorithm); err != nil {
return err
}

premptMap := map[string]bool{
"batch_scheduler_enabled": config.SchedulerConfig.PreemptionConfig.BatchSchedulerEnabled,
"service_scheduler_enabled": config.SchedulerConfig.PreemptionConfig.ServiceSchedulerEnabled,
"system_scheduler_enabled": config.SchedulerConfig.PreemptionConfig.SystemSchedulerEnabled,
}
return d.Set("preemption_config", premptMap)
}
94 changes: 94 additions & 0 deletions nomad/resource_scheduler_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package nomad

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
)

func TestSchedulerConfig_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testProviders,
CheckDestroy: testFinalConfiguration,
Steps: []resource.TestStep{
{
Config: testAccNomadSchedulerConfigSpread,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"nomad_scheduler_config.config",
"scheduler_algorithm",
"spread",
),
resource.TestCheckResourceAttr(
"nomad_scheduler_config.config",
"preemption_config.batch_scheduler_enabled",
"true",
),
resource.TestCheckResourceAttr(
"nomad_scheduler_config.config",
"preemption_config.service_scheduler_enabled",
"true",
),
resource.TestCheckResourceAttr(
"nomad_scheduler_config.config",
"preemption_config.system_scheduler_enabled",
"true",
),
),
},
{
Config: testAccNomadSchedulerConfigBinpack,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"nomad_scheduler_config.config",
"scheduler_algorithm",
"binpack",
),
resource.TestCheckResourceAttr(
"nomad_scheduler_config.config",
"preemption_config.batch_scheduler_enabled",
"false",
),
resource.TestCheckResourceAttr(
"nomad_scheduler_config.config",
"preemption_config.service_scheduler_enabled",
"true",
),
resource.TestCheckResourceAttr(
"nomad_scheduler_config.config",
"preemption_config.system_scheduler_enabled",
"false",
),
),
},
},
})
}

const testAccNomadSchedulerConfigSpread = `
resource "nomad_scheduler_config" "config" {
scheduler_algorithm = "spread"
preemption_config = {
system_scheduler_enabled = true
batch_scheduler_enabled = true
service_scheduler_enabled = true
}
}
`

const testAccNomadSchedulerConfigBinpack = `
resource "nomad_scheduler_config" "config" {
scheduler_algorithm = "binpack"
preemption_config = {
system_scheduler_enabled = false
batch_scheduler_enabled = false
service_scheduler_enabled = true
}
}
`

// for details on why this is the way it is, checkout the comments on
// resourceSchedulerConfigurationDelete.
func testFinalConfiguration(_ *terraform.State) error { return nil }
41 changes: 41 additions & 0 deletions website/docs/r/scheduler_config.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
layout: "nomad"
page_title: "Nomad: nomad_scheduler_config"
sidebar_current: "docs-nomad-scheduler-config"
description: |-
Manages scheduler configuration on the Nomad server.
---

# nomad_scheduler_config

Manages scheduler configuration of the Nomad cluster.

~> **Warning:** destroying this resource will not have any effect in the
cluster configuration, since there's no clear definition of what a destroy
action should do. The cluster will be left as-is and only the state reference
will be removed.

## Example Usage

Set cluster scheduler configuration:

```hcl
resource "nomad_scheduler_config" "config" {
scheduler_algorithm = "spread"
preemption_config = {
system_scheduler_enabled = true
batch_scheduler_enabled = true
service_scheduler_enabled = true
}
}
```

## Argument Reference

The following arguments are supported:

- `algorithm` `(string: "binpack")` - Specifies whether scheduler binpacks or spreads allocations on available nodes. Possible values are `binpack` and `spread`.
- `preemption_config` `(map[string]bool)` - Options to enable preemption for various schedulers.
- `system_scheduler_enabled` `(bool: true)` - Specifies whether preemption for system jobs is enabled. Note that if this is set to true, then system jobs can preempt any other jobs.
- `batch_scheduler_enabled` `(bool: false")` - Specifies whether preemption for batch jobs is enabled. Note that if this is set to true, then batch jobs can preempt any other jobs.
- `service_scheduler_enabled` `(bool: false)` - Specifies whether preemption for service jobs is enabled. Note that if this is set to true, then service jobs can preempt any other jobs.
3 changes: 3 additions & 0 deletions website/nomad.erb
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@
<li<%= sidebar_current("docs-nomad-resource-sentinel-policy") %>>
<a href="/docs/providers/nomad/r/sentinel_policy.html">nomad_sentinel_policy</a>
</li>
<li<%= sidebar_current("docs-nomad-resource-scheduler-config") %>>
<a href="/docs/providers/nomad/r/scheduler_config.html">nomad_scheduler_config</a>
</li>
<li<%= sidebar_current("docs-nomad-resource-volume-policy") %>>
<a href="/docs/providers/nomad/r/volume.html">nomad_volume</a>
</li>
Expand Down

0 comments on commit b731ef4

Please sign in to comment.