Adds build_auth_token to Habitat Provisioner

First successful run with private origin and HAB_AUTH_TOKEN set

Update struct, schema, and decodeConfig names to more sensible versions

Cleaned up formatting

Update habitat provisioner docs

Remove unused unitstring
This commit is contained in:
Rob Campbell 2017-12-11 18:15:10 -05:00
parent f1079257ac
commit 29f70bc112
2 changed files with 78 additions and 40 deletions

View File

@ -1,6 +1,7 @@
package habitat package habitat
import ( import (
"bytes"
"context" "context"
"errors" "errors"
"fmt" "fmt"
@ -9,6 +10,7 @@ import (
"net/url" "net/url"
"path" "path"
"strings" "strings"
"text/template"
"time" "time"
"github.com/hashicorp/terraform/communicator" "github.com/hashicorp/terraform/communicator"
@ -19,15 +21,20 @@ import (
) )
const installURL = "https://raw.githubusercontent.com/habitat-sh/habitat/master/components/hab/install.sh" const installURL = "https://raw.githubusercontent.com/habitat-sh/habitat/master/components/hab/install.sh"
const systemdUnit = `[Unit] const systemdUnit = `
[Unit]
Description=Habitat Supervisor Description=Habitat Supervisor
[Service] [Service]
ExecStart=/bin/hab sup run %s ExecStart=/bin/hab sup run {{ .SupOptions }}
Restart=on-failure Restart=on-failure
{{ if .BuilderAuthToken -}}
Environment="HAB_AUTH_TOKEN={{ .BuilderAuthToken }}"
{{ end -}}
[Install] [Install]
WantedBy=default.target` WantedBy=default.target
`
var serviceTypes = map[string]bool{"unmanaged": true, "systemd": true} var serviceTypes = map[string]bool{"unmanaged": true, "systemd": true}
var updateStrategies = map[string]bool{"at-once": true, "rolling": true, "none": true} var updateStrategies = map[string]bool{"at-once": true, "rolling": true, "none": true}
@ -36,22 +43,24 @@ var topologies = map[string]bool{"leader": true, "standalone": true}
type provisionFn func(terraform.UIOutput, communicator.Communicator) error type provisionFn func(terraform.UIOutput, communicator.Communicator) error
type provisioner struct { type provisioner struct {
Version string Version string
Services []Service Services []Service
PermanentPeer bool PermanentPeer bool
ListenGossip string ListenGossip string
ListenHTTP string ListenHTTP string
Peer string Peer string
RingKey string RingKey string
RingKeyContent string RingKeyContent string
SkipInstall bool SkipInstall bool
UseSudo bool UseSudo bool
ServiceType string ServiceType string
URL string URL string
Channel string Channel string
Events string Events string
OverrideName string OverrideName string
Organization string Organization string
BuilderAuthToken string
SupOptions string
} }
func Provisioner() terraform.ResourceProvisioner { func Provisioner() terraform.ResourceProvisioner {
@ -116,6 +125,10 @@ func Provisioner() terraform.ResourceProvisioner {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
}, },
"builder_auth_token": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"service": &schema.Schema{ "service": &schema.Schema{
Type: schema.TypeSet, Type: schema.TypeSet,
Elem: &schema.Resource{ Elem: &schema.Resource{
@ -326,21 +339,22 @@ func (b *Bind) toBindString() string {
func decodeConfig(d *schema.ResourceData) (*provisioner, error) { func decodeConfig(d *schema.ResourceData) (*provisioner, error) {
p := &provisioner{ p := &provisioner{
Version: d.Get("version").(string), Version: d.Get("version").(string),
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),
ServiceType: d.Get("service_type").(string), ServiceType: d.Get("service_type").(string),
RingKey: d.Get("ring_key").(string), RingKey: d.Get("ring_key").(string),
RingKeyContent: d.Get("ring_key_content").(string), RingKeyContent: d.Get("ring_key_content").(string),
PermanentPeer: d.Get("permanent_peer").(bool), PermanentPeer: d.Get("permanent_peer").(bool),
ListenGossip: d.Get("listen_gossip").(string), ListenGossip: d.Get("listen_gossip").(string),
ListenHTTP: d.Get("listen_http").(string), ListenHTTP: d.Get("listen_http").(string),
URL: d.Get("url").(string), URL: d.Get("url").(string),
Channel: d.Get("channel").(string), Channel: d.Get("channel").(string),
Events: d.Get("events").(string), Events: d.Get("events").(string),
OverrideName: d.Get("override_name").(string), OverrideName: d.Get("override_name").(string),
Organization: d.Get("organization").(string), Organization: d.Get("organization").(string),
BuilderAuthToken: d.Get("builder_auth_token").(string),
} }
return p, nil return p, nil
@ -506,6 +520,8 @@ func (p *provisioner) startHab(o terraform.UIOutput, comm communicator.Communica
options += fmt.Sprintf(" --org %s", p.Organization) options += fmt.Sprintf(" --org %s", p.Organization)
} }
p.SupOptions = options
switch p.ServiceType { switch p.ServiceType {
case "unmanaged": case "unmanaged":
return p.startHabUnmanaged(o, comm, options) return p.startHabUnmanaged(o, comm, options)
@ -519,6 +535,7 @@ func (p *provisioner) startHab(o terraform.UIOutput, comm communicator.Communica
func (p *provisioner) startHabUnmanaged(o terraform.UIOutput, comm communicator.Communicator, options string) error { func (p *provisioner) startHabUnmanaged(o terraform.UIOutput, comm communicator.Communicator, options string) error {
// Create the sup directory for the log file // Create the sup directory for the log file
var command string var command string
var token string
if p.UseSudo { if p.UseSudo {
command = "sudo mkdir -p /hab/sup/default && sudo chmod o+w /hab/sup/default" command = "sudo mkdir -p /hab/sup/default && sudo chmod o+w /hab/sup/default"
} else { } else {
@ -528,22 +545,34 @@ func (p *provisioner) startHabUnmanaged(o terraform.UIOutput, comm communicator.
return err return err
} }
if p.BuilderAuthToken != "" {
token = fmt.Sprintf("env HAB_AUTH_TOKEN=%s", p.BuilderAuthToken)
}
if p.UseSudo { if p.UseSudo {
command = fmt.Sprintf("(setsid sudo hab sup run %s > /hab/sup/default/sup.log 2>&1 &) ; sleep 1", options) command = fmt.Sprintf("(%s setsid sudo -E hab sup run %s > /hab/sup/default/sup.log 2>&1 &) ; sleep 1", token, options)
} else { } else {
command = fmt.Sprintf("(setsid hab sup run %s > /hab/sup/default/sup.log 2>&1 <&1 &) ; sleep 1", options) command = fmt.Sprintf("(%s setsid hab sup run %s > /hab/sup/default/sup.log 2>&1 <&1 &) ; sleep 1", token, options)
} }
return p.runCommand(o, comm, command) return p.runCommand(o, comm, command)
} }
func (p *provisioner) startHabSystemd(o terraform.UIOutput, comm communicator.Communicator, options string) error { func (p *provisioner) startHabSystemd(o terraform.UIOutput, comm communicator.Communicator, options string) error {
unitString := fmt.Sprintf(systemdUnit, options) // Create a new template and parse the client config into it
unitString := template.Must(template.New("hab-supervisor.service").Parse(systemdUnit))
var buf bytes.Buffer
err := unitString.Execute(&buf, p)
if err != nil {
return fmt.Errorf("Error executing %s template: %s", "hab-supervisor.service", err)
}
var command string var command string
if p.UseSudo { if p.UseSudo {
command = fmt.Sprintf("sudo echo '%s' | sudo tee /etc/systemd/system/hab-supervisor.service > /dev/null", unitString) command = fmt.Sprintf("sudo echo '%s' | sudo tee /etc/systemd/system/hab-supervisor.service > /dev/null", &buf)
} else { } else {
command = fmt.Sprintf("echo '%s' | tee /etc/systemd/system/hab-supervisor.service > /dev/null", unitString) command = fmt.Sprintf("echo '%s' | tee /etc/systemd/system/hab-supervisor.service > /dev/null", &buf)
} }
if err := p.runCommand(o, comm, command); err != nil { if err := p.runCommand(o, comm, command); err != nil {
@ -582,6 +611,11 @@ func (p *provisioner) startHabService(o terraform.UIOutput, comm communicator.Co
} else { } else {
command = fmt.Sprintf("env HAB_NONINTERACTIVE=true hab pkg install %s", service.Name) command = fmt.Sprintf("env HAB_NONINTERACTIVE=true hab pkg install %s", service.Name)
} }
if p.BuilderAuthToken != "" {
command = fmt.Sprintf("env HAB_AUTH_TOKEN=%s %s", p.BuilderAuthToken, command)
}
if err := p.runCommand(o, comm, command); err != nil { if err := p.runCommand(o, comm, command); err != nil {
return err return err
} }
@ -621,7 +655,10 @@ func (p *provisioner) startHabService(o terraform.UIOutput, comm communicator.Co
} }
command = fmt.Sprintf("hab svc load %s %s", service.Name, options) command = fmt.Sprintf("hab svc load %s %s", service.Name, options)
if p.UseSudo { if p.UseSudo {
command = fmt.Sprintf("sudo %s", command) command = fmt.Sprintf("sudo -E %s", command)
}
if p.BuilderAuthToken != "" {
command = fmt.Sprintf("env HAB_AUTH_TOKEN=%s %s", p.BuilderAuthToken, command)
} }
return p.runCommand(o, comm, command) return p.runCommand(o, comm, command)
} }

View File

@ -60,6 +60,7 @@ There are 2 configuration levels, `supervisor` and `service`. Configuration pla
* `events (string)` - (Optional) Name of the service group running a Habitat EventSrv to forward Supervisor and service event data to. (Defaults to none) * `events (string)` - (Optional) Name of the service group running a Habitat EventSrv to forward Supervisor and service event data to. (Defaults to none)
* `override_name (string)` - (Optional) The name of the Supervisor (Defaults to `default`) * `override_name (string)` - (Optional) The name of the Supervisor (Defaults to `default`)
* `organization (string)` - (Optional) The organization that the Supervisor and it's subsequent services are part of. (Defaults to `default`) * `organization (string)` - (Optional) The organization that the Supervisor and it's subsequent services are part of. (Defaults to `default`)
* `builder_auth_token (string)` - (Optional) The builder authorization token when using a private origin. (Defaults to none)
### Service Arguments ### Service Arguments
* `name (string)` - (Required) The Habitat package identifier of the service to run. (ie `core/haproxy` or `core/redis/3.2.4/20171002182640`) * `name (string)` - (Required) The Habitat package identifier of the service to run. (ie `core/haproxy` or `core/redis/3.2.4/20171002182640`)