Habitat License Acceptance changes. These changes add a new argument that allows users to accept Habitat End User License.
It also containts doc updates for Habitat and Chef provisioner
This commit is contained in:
parent
72f9385285
commit
50a6c69ab5
|
@ -11,6 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
version "github.com/hashicorp/go-version"
|
||||||
"github.com/hashicorp/terraform/communicator"
|
"github.com/hashicorp/terraform/communicator"
|
||||||
"github.com/hashicorp/terraform/communicator/remote"
|
"github.com/hashicorp/terraform/communicator/remote"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
@ -60,6 +61,7 @@ type provisioner struct {
|
||||||
Organization string
|
Organization string
|
||||||
BuilderAuthToken string
|
BuilderAuthToken string
|
||||||
SupOptions string
|
SupOptions string
|
||||||
|
AcceptLicense bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func Provisioner() terraform.ResourceProvisioner {
|
func Provisioner() terraform.ResourceProvisioner {
|
||||||
|
@ -88,6 +90,10 @@ func Provisioner() terraform.ResourceProvisioner {
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: true,
|
Default: true,
|
||||||
},
|
},
|
||||||
|
"accept_license": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
"permanent_peer": &schema.Schema{
|
"permanent_peer": &schema.Schema{
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -290,6 +296,26 @@ func validateFn(c *terraform.ResourceConfig) (ws []string, es []error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v, ok := c.Get("version")
|
||||||
|
if ok && v != nil && strings.TrimSpace(v.(string)) != "" {
|
||||||
|
if _, err := version.NewVersion(v.(string)); err != nil {
|
||||||
|
es = append(es, errors.New(v.(string)+" is not a valid version."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptLicense, ok := c.Get("accept_license")
|
||||||
|
if ok && !acceptLicense.(bool) {
|
||||||
|
if v != nil && strings.TrimSpace(v.(string)) != "" {
|
||||||
|
versionOld, _ := version.NewVersion("0.79.0")
|
||||||
|
versionRequired, _ := version.NewVersion(v.(string))
|
||||||
|
if versionRequired.GreaterThan(versionOld) {
|
||||||
|
es = append(es, errors.New("Habitat end user license agreement needs to be accepted, set the accept_license argument to true to accept"))
|
||||||
|
}
|
||||||
|
} else { // blank means latest version
|
||||||
|
es = append(es, errors.New("Habitat end user license agreement needs to be accepted, set the accept_license argument to true to accept"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Validate service level configs
|
// Validate service level configs
|
||||||
services, ok := c.Get("service")
|
services, ok := c.Get("service")
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -299,7 +325,6 @@ func validateFn(c *terraform.ResourceConfig) (ws []string, es []error) {
|
||||||
es = append(es, fmt.Errorf("service %d: must be a block", i))
|
es = append(es, fmt.Errorf("service %d: must be a block", i))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
strategy, ok := service["strategy"].(string)
|
strategy, ok := service["strategy"].(string)
|
||||||
if ok && !updateStrategies[strategy] {
|
if ok && !updateStrategies[strategy] {
|
||||||
es = append(es, errors.New(strategy+" is not a valid update strategy."))
|
es = append(es, errors.New(strategy+" is not a valid update strategy."))
|
||||||
|
@ -357,6 +382,7 @@ func decodeConfig(d *schema.ResourceData) (*provisioner, error) {
|
||||||
Peer: d.Get("peer").(string),
|
Peer: d.Get("peer").(string),
|
||||||
Services: getServices(d.Get("service").(*schema.Set).List()),
|
Services: getServices(d.Get("service").(*schema.Set).List()),
|
||||||
UseSudo: d.Get("use_sudo").(bool),
|
UseSudo: d.Get("use_sudo").(bool),
|
||||||
|
AcceptLicense: d.Get("accept_license").(bool),
|
||||||
ServiceType: d.Get("service_type").(string),
|
ServiceType: d.Get("service_type").(string),
|
||||||
ServiceName: d.Get("service_name").(string),
|
ServiceName: d.Get("service_name").(string),
|
||||||
RingKey: d.Get("ring_key").(string),
|
RingKey: d.Get("ring_key").(string),
|
||||||
|
@ -467,6 +493,17 @@ func (p *provisioner) installHab(o terraform.UIOutput, comm communicator.Communi
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accept the license
|
||||||
|
if p.AcceptLicense {
|
||||||
|
command = fmt.Sprintf("export HAB_LICENSE=accept; hab -V")
|
||||||
|
if p.UseSudo {
|
||||||
|
command = fmt.Sprintf("sudo HAB_LICENSE=accept hab -V")
|
||||||
|
}
|
||||||
|
if err := p.runCommand(o, comm, command); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := p.createHabUser(o, comm); err != nil {
|
if err := p.createHabUser(o, comm); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -608,6 +645,7 @@ func (p *provisioner) createHabUser(o terraform.UIOutput, comm communicator.Comm
|
||||||
if p.UseSudo {
|
if p.UseSudo {
|
||||||
command = fmt.Sprintf("sudo %s", command)
|
command = fmt.Sprintf("sudo %s", command)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := p.runCommand(o, comm, command); err != nil {
|
if err := p.runCommand(o, comm, command); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,10 @@ func TestProvisioner(t *testing.T) {
|
||||||
|
|
||||||
func TestResourceProvisioner_Validate_good(t *testing.T) {
|
func TestResourceProvisioner_Validate_good(t *testing.T) {
|
||||||
c := testConfig(t, map[string]interface{}{
|
c := testConfig(t, map[string]interface{}{
|
||||||
"peer": "1.2.3.4",
|
"peer": "1.2.3.4",
|
||||||
"version": "0.32.0",
|
"version": "0.32.0",
|
||||||
"service_type": "systemd",
|
"service_type": "systemd",
|
||||||
|
"accept_license": false,
|
||||||
})
|
})
|
||||||
|
|
||||||
warn, errs := Provisioner().Validate(c)
|
warn, errs := Provisioner().Validate(c)
|
||||||
|
@ -42,13 +43,15 @@ func TestResourceProvisioner_Validate_bad(t *testing.T) {
|
||||||
if len(warn) > 0 {
|
if len(warn) > 0 {
|
||||||
t.Fatalf("Warnings: %v", warn)
|
t.Fatalf("Warnings: %v", warn)
|
||||||
}
|
}
|
||||||
if len(errs) != 1 {
|
//Two errors, one for service_type, other for missing required accept_license argument
|
||||||
t.Fatalf("Should have one error")
|
if len(errs) != 2 {
|
||||||
|
t.Fatalf("Should have one errors, got %d", len(errs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceProvisioner_Validate_bad_service_config(t *testing.T) {
|
func TestResourceProvisioner_Validate_bad_service_config(t *testing.T) {
|
||||||
c := testConfig(t, map[string]interface{}{
|
c := testConfig(t, map[string]interface{}{
|
||||||
|
"accept_license": true,
|
||||||
"service": []interface{}{
|
"service": []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"name": "core/foo",
|
"name": "core/foo",
|
||||||
|
|
|
@ -19,6 +19,8 @@ The `chef` provisioner has some prerequisites for specific connection types:
|
||||||
* For `ssh` type connections, `cURL` must be available on the remote host.
|
* For `ssh` type connections, `cURL` must be available on the remote host.
|
||||||
* For `winrm` connections, `PowerShell 2.0` must be available on the remote host.
|
* For `winrm` connections, `PowerShell 2.0` must be available on the remote host.
|
||||||
|
|
||||||
|
[Chef end user license agreement](https://www.chef.io/end-user-license-agreement/) must be accepted by setting `chef_license` to `accept` in `client_options` argument unless you are installing an old version of Chef client.
|
||||||
|
|
||||||
Without these prerequisites, your provisioning execution will fail.
|
Without these prerequisites, your provisioning execution will fail.
|
||||||
|
|
||||||
## Example usage
|
## Example usage
|
||||||
|
@ -43,6 +45,7 @@ resource "aws_instance" "web" {
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
environment = "_default"
|
environment = "_default"
|
||||||
|
client_options = ["chef_license 'accept'"]
|
||||||
run_list = ["cookbook::recipe"]
|
run_list = ["cookbook::recipe"]
|
||||||
node_name = "webserver1"
|
node_name = "webserver1"
|
||||||
secret_key = "${file("../encrypted_data_bag_secret")}"
|
secret_key = "${file("../encrypted_data_bag_secret")}"
|
||||||
|
|
|
@ -30,6 +30,7 @@ resource "aws_instance" "redis" {
|
||||||
peer = "${aws_instance.redis.0.private_ip}"
|
peer = "${aws_instance.redis.0.private_ip}"
|
||||||
use_sudo = true
|
use_sudo = true
|
||||||
service_type = "systemd"
|
service_type = "systemd"
|
||||||
|
accept_license = true
|
||||||
|
|
||||||
service {
|
service {
|
||||||
name = "core/redis"
|
name = "core/redis"
|
||||||
|
@ -46,6 +47,7 @@ resource "aws_instance" "redis" {
|
||||||
There are 2 configuration levels, `supervisor` and `service`. Configuration placed directly within the `provisioner` block are supervisor configurations, and a provisioner can define zero or more services to run, and each service will have a `service` block within the `provisioner`. A `service` block can also contain zero or more `bind` blocks to create service group bindings.
|
There are 2 configuration levels, `supervisor` and `service`. Configuration placed directly within the `provisioner` block are supervisor configurations, and a provisioner can define zero or more services to run, and each service will have a `service` block within the `provisioner`. A `service` block can also contain zero or more `bind` blocks to create service group bindings.
|
||||||
|
|
||||||
### Supervisor Arguments
|
### Supervisor Arguments
|
||||||
|
* `accept_license (bool)` - (Required) Set to true to accept [Habitat end user license agreement](https://www.chef.io/end-user-license-agreement/)
|
||||||
* `version (string)` - (Optional) The Habitat version to install on the remote machine. If not specified, the latest available version is used.
|
* `version (string)` - (Optional) The Habitat version to install on the remote machine. If not specified, the latest available version is used.
|
||||||
* `use_sudo (bool)` - (Optional) Use `sudo` when executing remote commands. Required when the user specified in the `connection` block is not `root`. (Defaults to `true`)
|
* `use_sudo (bool)` - (Optional) Use `sudo` when executing remote commands. Required when the user specified in the `connection` block is not `root`. (Defaults to `true`)
|
||||||
* `service_type (string)` - (Optional) Method used to run the Habitat supervisor. Valid options are `unmanaged` and `systemd`. (Defaults to `systemd`)
|
* `service_type (string)` - (Optional) Method used to run the Habitat supervisor. Valid options are `unmanaged` and `systemd`. (Defaults to `systemd`)
|
||||||
|
|
Loading…
Reference in New Issue