Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

command/agent: Google Compute Engine host discovery #2570

Merged
merged 7 commits into from
Jan 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
312 changes: 256 additions & 56 deletions command/agent/command.go

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions command/agent/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,33 @@ func TestDiscoverEC2Hosts(t *testing.T) {
}
}

func TestDiscoverGCEHosts(t *testing.T) {
if os.Getenv("GCE_PROJECT") == "" {
t.Skip("GCE_PROJECT not set, skipping")
}

if os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") == "" && os.Getenv("GCE_CONFIG_CREDENTIALS") == "" {
t.Skip("GOOGLE_APPLICATION_CREDENTIALS or GCE_CONFIG_CREDENTIALS not set, skipping")
}

c := &Config{
RetryJoinGCE: RetryJoinGCE{
ProjectName: os.Getenv("GCE_PROJECT"),
ZonePattern: os.Getenv("GCE_ZONE"),
TagValue: "consulrole-server",
CredentialsFile: os.Getenv("GCE_CONFIG_CREDENTIALS"),
},
}

servers, err := c.discoverGCEHosts(log.New(os.Stderr, "", log.LstdFlags))
if err != nil {
t.Fatal(err)
}
if len(servers) != 3 {
t.Fatalf("bad: %v", servers)
}
}

func TestSetupAgent_RPCUnixSocket_FileExists(t *testing.T) {
conf := nextConfig()
tmpDir, err := ioutil.TempDir("", "consul")
Expand Down
40 changes: 40 additions & 0 deletions command/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,31 @@ type RetryJoinEC2 struct {
SecretAccessKey string `mapstructure:"secret_access_key"`
}

// RetryJoinGCE is used to configure discovery of instances via Google Compute
// Engine's API.
type RetryJoinGCE struct {
// The name of the project the instances reside in.
ProjectName string `mapstructure:"project_name"`

// A regular expression (RE2) pattern for the zones you want to discover the instances in.
// Example: us-west1-.*, or us-(?west|east).*.
ZonePattern string `mapstructure:"zone_pattern"`

// The tag value to search for when filtering instances.
TagValue string `mapstructure:"tag_value"`

// A path to a JSON file with the service account credentials necessary to
// connect to GCE. If this is not defined, the following chain is respected:
// 1. A JSON file whose path is specified by the
// GOOGLE_APPLICATION_CREDENTIALS environment variable.
// 2. A JSON file in a location known to the gcloud command-line tool.
// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json.
// On other systems, $HOME/.config/gcloud/application_default_credentials.json.
// 3. On Google Compute Engine, it fetches credentials from the metadata
// server. (In this final case any provided scopes are ignored.)
CredentialsFile string `mapstructure:"credentials_file"`
}

// Performance is used to tune the performance of Consul's subsystems.
type Performance struct {
// RaftMultiplier is an integer multiplier used to scale Raft timing
Expand Down Expand Up @@ -426,6 +451,9 @@ type Config struct {
// RetryJoinEC2 configuration
RetryJoinEC2 RetryJoinEC2 `mapstructure:"retry_join_ec2"`

// The config struct for the GCE tag server discovery feature.
RetryJoinGCE RetryJoinGCE `mapstructure:"retry_join_gce"`

// RetryJoinWan is a list of addresses to join -wan with retry enabled.
RetryJoinWan []string `mapstructure:"retry_join_wan"`

Expand Down Expand Up @@ -1446,6 +1474,18 @@ func MergeConfig(a, b *Config) *Config {
if b.RetryJoinEC2.TagValue != "" {
result.RetryJoinEC2.TagValue = b.RetryJoinEC2.TagValue
}
if b.RetryJoinGCE.ProjectName != "" {
result.RetryJoinGCE.ProjectName = b.RetryJoinGCE.ProjectName
}
if b.RetryJoinGCE.ZonePattern != "" {
result.RetryJoinGCE.ZonePattern = b.RetryJoinGCE.ZonePattern
}
if b.RetryJoinGCE.TagValue != "" {
result.RetryJoinGCE.TagValue = b.RetryJoinGCE.TagValue
}
if b.RetryJoinGCE.CredentialsFile != "" {
result.RetryJoinGCE.CredentialsFile = b.RetryJoinGCE.CredentialsFile
}
if b.RetryMaxAttemptsWan != 0 {
result.RetryMaxAttemptsWan = b.RetryMaxAttemptsWan
}
Expand Down
26 changes: 26 additions & 0 deletions command/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,32 @@ func TestRetryJoinEC2(t *testing.T) {
}
}

func TestRetryJoinGCE(t *testing.T) {
input := `{"retry_join_gce": {
"project_name": "test-project",
"zone_pattern": "us-west1-a",
"tag_value": "consul-server",
"credentials_file": "/path/to/foo.json"
}}`
config, err := DecodeConfig(bytes.NewReader([]byte(input)))
if err != nil {
t.Fatalf("err: %s", err)
}

if config.RetryJoinGCE.ProjectName != "test-project" {
t.Fatalf("bad: %#v", config)
}
if config.RetryJoinGCE.ZonePattern != "us-west1-a" {
t.Fatalf("bad: %#v", config)
}
if config.RetryJoinGCE.TagValue != "consul-server" {
t.Fatalf("bad: %#v", config)
}
if config.RetryJoinGCE.CredentialsFile != "/path/to/foo.json" {
t.Fatalf("bad: %#v", config)
}
}

func TestDecodeConfig_Performance(t *testing.T) {
input := `{"performance": { "raft_multiplier": 3 }}`
config, err := DecodeConfig(bytes.NewReader([]byte(input)))
Expand Down
202 changes: 202 additions & 0 deletions vendor/cloud.google.com/go/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading