Use upstream high-level SCADA provider

This commit is contained in:
Jeff Mitchell 2016-06-01 16:34:59 -04:00
parent 0f84d8968b
commit b4f25e0b04
4 changed files with 113 additions and 157 deletions

View file

@ -21,7 +21,7 @@ import (
"github.com/hashicorp/logutils" "github.com/hashicorp/logutils"
"github.com/hashicorp/nomad/helper/flag-slice" "github.com/hashicorp/nomad/helper/flag-slice"
"github.com/hashicorp/nomad/helper/gated-writer" "github.com/hashicorp/nomad/helper/gated-writer"
scada "github.com/hashicorp/scada-client" "github.com/hashicorp/scada-client/scada"
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
@ -622,7 +622,26 @@ func (c *Command) setupSCADA(config *Config) error {
// Create the new provider and listener // Create the new provider and listener
c.Ui.Output("Connecting to Atlas: " + config.Atlas.Infrastructure) c.Ui.Output("Connecting to Atlas: " + config.Atlas.Infrastructure)
provider, list, err := NewProvider(config, c.logOutput)
scadaConfig := &scada.Config{
Service: "nomad",
Version: fmt.Sprintf("%s%s", config.Version, config.VersionPrerelease),
ResourceType: "nomad-cluster",
Meta: map[string]string{
"auto-join": strconv.FormatBool(config.Atlas.Join),
"region": config.Region,
"datacenter": config.Datacenter,
"client": strconv.FormatBool(config.Client != nil && config.Client.Enabled),
"server": strconv.FormatBool(config.Server != nil && config.Server.Enabled),
},
Atlas: scada.AtlasConfig{
Endpoint: config.Atlas.Endpoint,
Infrastructure: config.Atlas.Infrastructure,
Token: config.Atlas.Token,
},
}
provider, list, err := scada.NewHTTPProvider(scadaConfig, c.logOutput)
if err != nil { if err != nil {
return err return err
} }

View file

@ -1,112 +0,0 @@
package agent
import (
"net"
"reflect"
"testing"
"github.com/hashicorp/scada-client"
)
func TestProviderService(t *testing.T) {
conf := DefaultConfig()
conf.Version = "0.5.0"
conf.VersionPrerelease = "rc1"
conf.Atlas = &AtlasConfig{}
conf.Atlas.Join = true
conf.Server.Enabled = true
ps := ProviderService(conf)
expect := &client.ProviderService{
Service: "nomad",
ServiceVersion: "0.5.0rc1",
Capabilities: map[string]int{
"http": 1,
},
Meta: map[string]string{
"auto-join": "true",
"region": "global",
"datacenter": "dc1",
"client": "false",
"server": "true",
},
ResourceType: "nomad-cluster",
}
if !reflect.DeepEqual(ps, expect) {
t.Fatalf("bad: %v", ps)
}
}
func TestProviderConfig(t *testing.T) {
conf := DefaultConfig()
conf.Version = "0.5.0"
conf.VersionPrerelease = "rc1"
conf.Atlas = &AtlasConfig{}
conf.Atlas.Join = true
conf.Atlas.Infrastructure = "armon/test"
conf.Atlas.Token = "foobarbaz"
conf.Atlas.Endpoint = "foo.bar:1111"
conf.Server.Enabled = true
pc := ProviderConfig(conf)
expect := &client.ProviderConfig{
Service: &client.ProviderService{
Service: "nomad",
ServiceVersion: "0.5.0rc1",
Capabilities: map[string]int{
"http": 1,
},
Meta: map[string]string{
"auto-join": "true",
"region": "global",
"datacenter": "dc1",
"client": "false",
"server": "true",
},
ResourceType: "nomad-cluster",
},
Handlers: map[string]client.CapabilityProvider{
"http": nil,
},
Endpoint: "foo.bar:1111",
ResourceGroup: "armon/test",
Token: "foobarbaz",
}
if !reflect.DeepEqual(pc, expect) {
t.Fatalf("bad: %v", pc)
}
}
func TestSCADAListener(t *testing.T) {
list := newScadaListener("armon/test")
defer list.Close()
var raw interface{} = list
_, ok := raw.(net.Listener)
if !ok {
t.Fatalf("bad")
}
a, b := net.Pipe()
defer a.Close()
defer b.Close()
go list.Push(a)
out, err := list.Accept()
if err != nil {
t.Fatalf("err: %v", err)
}
if out != a {
t.Fatalf("bad")
}
}
func TestSCADAAddr(t *testing.T) {
var addr interface{} = &scadaAddr{"armon/test"}
_, ok := addr.(net.Addr)
if !ok {
t.Fatalf("bad")
}
}

View file

@ -1,4 +1,4 @@
package agent package scada
import ( import (
"crypto/tls" "crypto/tls"
@ -7,65 +7,107 @@ import (
"io" "io"
"net" "net"
"os" "os"
"strconv"
"sync" "sync"
"time" "time"
"github.com/hashicorp/scada-client" sc "github.com/hashicorp/scada-client"
) )
const ( const (
// providerService is the service name we use InfrastructureResource = "infrastructures"
providerService = "nomad" BoxesResource = "boxes"
SharesResource = "shares"
// resourceType is the type of resource we represent NomadClusterResource = "nomad-cluster"
// when connecting to SCADA
resourceType = "nomad-cluster"
) )
// ProviderService returns the service information for the provider // Provider wraps scada-client.Provider to allow most applications to only pull
func ProviderService(c *Config) *client.ProviderService { // in this package
return &client.ProviderService{ type Provider struct {
Service: providerService, *sc.Provider
ServiceVersion: fmt.Sprintf("%s%s", c.Version, c.VersionPrerelease),
Capabilities: map[string]int{
"http": 1,
},
Meta: map[string]string{
"auto-join": strconv.FormatBool(c.Atlas.Join),
"region": c.Region,
"datacenter": c.Datacenter,
"client": strconv.FormatBool(c.Client != nil && c.Client.Enabled),
"server": strconv.FormatBool(c.Server != nil && c.Server.Enabled),
},
ResourceType: resourceType,
}
} }
// ProviderConfig returns the configuration for the SCADA provider type AtlasConfig struct {
func ProviderConfig(c *Config) *client.ProviderConfig { // Endpoint is the SCADA endpoint used for Atlas integration. If empty, the
return &client.ProviderConfig{ // defaults from the provider are used.
Service: ProviderService(c), Endpoint string `mapstructure:"endpoint"`
Handlers: map[string]client.CapabilityProvider{
"http": nil, // The name of the infrastructure we belong to, e.g. "hashicorp/prod"
}, Infrastructure string `mapstructure:"infrastructure"`
// The Atlas authentication token
Token string `mapstructure:"token" json:"-"`
}
// Config holds the high-level information used to instantiate a SCADA provider
// and listener
type Config struct {
// The service name to use
Service string
// The version of the service
Version string
// The type of resource we represent
ResourceType string
// Metadata to send to along with the service information
Meta map[string]string
// If set, TLS certificate verification will be skipped. The value of the
// SCADA_INSECURE environment variable will be considered if this is false.
// If using SCADA_INSECURE, any non-empty value will trigger insecure mode.
Insecure bool
// Holds Atlas configuration
Atlas AtlasConfig
}
// ProviderService returns the service information for the provider
func providerService(c *Config) *sc.ProviderService {
ret := &sc.ProviderService{
Service: c.Service,
ServiceVersion: c.Version,
Capabilities: map[string]int{},
Meta: c.Meta,
ResourceType: c.ResourceType,
}
return ret
}
// providerConfig returns the configuration for the SCADA provider
func providerConfig(c *Config) *sc.ProviderConfig {
ret := &sc.ProviderConfig{
Service: providerService(c),
Handlers: map[string]sc.CapabilityProvider{},
Endpoint: c.Atlas.Endpoint, Endpoint: c.Atlas.Endpoint,
ResourceGroup: c.Atlas.Infrastructure, ResourceGroup: c.Atlas.Infrastructure,
Token: c.Atlas.Token, Token: c.Atlas.Token,
} }
return ret
} }
// NewProvider creates a new SCADA provider using the // NewProvider creates a new SCADA provider using the given configuration.
// given configuration. Requests for the HTTP capability // Requests for the HTTP capability are passed off to the listener that is
// are passed off to the listener that is returned. // returned.
func NewProvider(c *Config, logOutput io.Writer) (*client.Provider, net.Listener, error) { func NewHTTPProvider(c *Config, logOutput io.Writer) (*Provider, net.Listener, error) {
// Get the configuration of the provider // Get the configuration of the provider
config := ProviderConfig(c) config := providerConfig(c)
config.LogOutput = logOutput config.LogOutput = logOutput
// SCADA_INSECURE env variable is used for testing to disable // Set the HTTP capability
// TLS certificate verification. config.Service.Capabilities["http"] = 1
// SCADA_INSECURE env variable is used for testing to disable TLS
// certificate verification.
insecure := c.Insecure
if !insecure {
if os.Getenv("SCADA_INSECURE") != "" { if os.Getenv("SCADA_INSECURE") != "" {
insecure = true
}
}
if insecure {
config.TLSConfig = &tls.Config{ config.TLSConfig = &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
} }
@ -79,12 +121,13 @@ func NewProvider(c *Config, logOutput io.Writer) (*client.Provider, net.Listener
} }
// Create the provider // Create the provider
provider, err := client.NewProvider(config) provider, err := sc.NewProvider(config)
if err != nil { if err != nil {
list.Close() list.Close()
return nil, nil, err return nil, nil, err
} }
return provider, list, nil
return &Provider{provider}, list, nil
} }
// scadaListener is used to return a net.Listener for // scadaListener is used to return a net.Listener for

6
vendor/vendor.json vendored
View file

@ -540,6 +540,12 @@
"path": "github.com/hashicorp/scada-client", "path": "github.com/hashicorp/scada-client",
"revision": "84989fd23ad4cc0e7ad44d6a871fd793eb9beb0a" "revision": "84989fd23ad4cc0e7ad44d6a871fd793eb9beb0a"
}, },
{
"checksumSHA1": "YQamL+KX0yqqM+aiwWaFy2FZEyE=",
"path": "github.com/hashicorp/scada-client/scada",
"revision": "225f7ae4780b59d1bd990de93cae7496bade95a0",
"revisionTime": "2016-06-01T18:41:54Z"
},
{ {
"comment": "v0.7.0-18-gc4c55f1", "comment": "v0.7.0-18-gc4c55f1",
"path": "github.com/hashicorp/serf/coordinate", "path": "github.com/hashicorp/serf/coordinate",