From 6f60bd4fc244e14d627b9158b881468254d9c6f9 Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 15:38:19 +0900 Subject: [PATCH 01/18] fix the key name s/ami_id/ami-id/g --- spec/linux/cloud.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/linux/cloud.go b/spec/linux/cloud.go index ba2126356..10408b9ee 100644 --- a/spec/linux/cloud.go +++ b/spec/linux/cloud.go @@ -53,7 +53,7 @@ func (g *CloudGenerator) Generate() (interface{}, error) { "instance-type", "placement/availability-zone", "security-groups", - "ami_id", + "ami-id", "hostname", "local-hostname", "public-hostname", From 34439a549f242235568d3107bb3f65e45c3e1668 Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 15:43:44 +0900 Subject: [PATCH 02/18] enhance log output --- spec/linux/cloud.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/linux/cloud.go b/spec/linux/cloud.go index 10408b9ee..71fbf9158 100644 --- a/spec/linux/cloud.go +++ b/spec/linux/cloud.go @@ -81,7 +81,7 @@ func (g *CloudGenerator) Generate() (interface{}, error) { metadata[key] = string(body) cloudLogger.Debugf("results %s:%s", key, string(body)) } else { - cloudLogger.Warningf("Status code of the result of requesting metadata is '%d'", resp.StatusCode) + cloudLogger.Warningf("Status code of the result of requesting metadata '%s' is '%d'", key, resp.StatusCode) } } From e96f7139fc7f77c63bf14d219f02323affc9601b Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 16:10:06 +0900 Subject: [PATCH 03/18] collect cloud spec in any os --- command/command_freebsd.go | 9 ++++++++- command/command_linux.go | 2 +- command/command_windows.go | 9 ++++++++- spec/{linux => }/cloud.go | 7 +++---- spec/{linux => }/cloud_test.go | 4 +--- 5 files changed, 21 insertions(+), 10 deletions(-) rename spec/{linux => }/cloud.go (98%) rename spec/{linux => }/cloud_test.go (97%) diff --git a/command/command_freebsd.go b/command/command_freebsd.go index 76a4e45d1..538e818c4 100644 --- a/command/command_freebsd.go +++ b/command/command_freebsd.go @@ -9,12 +9,19 @@ import ( ) func specGenerators() []spec.Generator { - return []spec.Generator{ + specs := []spec.Generator{ &specFreebsd.KernelGenerator{}, &specFreebsd.MemoryGenerator{}, &specFreebsd.CPUGenerator{}, &specFreebsd.FilesystemGenerator{}, } + cloudGenerator, err := spec.NewCloudGenerator("") + if err != nil { + logger.Errorf("Failed to create cloudGenerator: %s", err.Error()) + } else { + specs = append(specs, cloudGenerator) + } + return specs } func interfaceGenerator() spec.Generator { diff --git a/command/command_linux.go b/command/command_linux.go index 8ad6ee397..c4627ee7a 100644 --- a/command/command_linux.go +++ b/command/command_linux.go @@ -16,7 +16,7 @@ func specGenerators() []spec.Generator { &specLinux.BlockDeviceGenerator{}, &specLinux.FilesystemGenerator{}, } - cloudGenerator, err := specLinux.NewCloudGenerator("") + cloudGenerator, err := spec.NewCloudGenerator("") if err != nil { logger.Errorf("Failed to create cloudGenerator: %s", err.Error()) } else { diff --git a/command/command_windows.go b/command/command_windows.go index 5585e406f..4672e4650 100644 --- a/command/command_windows.go +++ b/command/command_windows.go @@ -9,13 +9,20 @@ import ( ) func specGenerators() []spec.Generator { - return []spec.Generator{ + specs := []spec.Generator{ &specWindows.KernelGenerator{}, &specWindows.CPUGenerator{}, &specWindows.MemoryGenerator{}, &specWindows.BlockDeviceGenerator{}, &specWindows.FilesystemGenerator{}, } + cloudGenerator, err := spec.NewCloudGenerator("") + if err != nil { + logger.Errorf("Failed to create cloudGenerator: %s", err.Error()) + } else { + specs = append(specs, cloudGenerator) + } + return specs } func interfaceGenerator() spec.Generator { diff --git a/spec/linux/cloud.go b/spec/cloud.go similarity index 98% rename from spec/linux/cloud.go rename to spec/cloud.go index 71fbf9158..4c2547402 100644 --- a/spec/linux/cloud.go +++ b/spec/cloud.go @@ -1,13 +1,12 @@ -// +build linux - -package linux +package spec import ( - "github.com/mackerelio/mackerel-agent/logging" "io/ioutil" "net/http" "net/url" "time" + + "github.com/mackerelio/mackerel-agent/logging" ) // This Generator collects metadata about cloud instances. diff --git a/spec/linux/cloud_test.go b/spec/cloud_test.go similarity index 97% rename from spec/linux/cloud_test.go rename to spec/cloud_test.go index 68cf32f50..7620b60fc 100644 --- a/spec/linux/cloud_test.go +++ b/spec/cloud_test.go @@ -1,6 +1,4 @@ -// +build linux - -package linux +package spec import ( "fmt" From 105afbdd593785b1aed97f6c63a9efe0095628fe Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 17:01:54 +0900 Subject: [PATCH 04/18] define var ec2BaseURL, gcpBaseURL, digitalOceanBaseURL *url.URL --- spec/cloud.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/cloud.go b/spec/cloud.go index 4c2547402..912847c3f 100644 --- a/spec/cloud.go +++ b/spec/cloud.go @@ -27,6 +27,14 @@ func (g *CloudGenerator) Key() string { var cloudLogger = logging.GetLogger("spec.cloud") +var ec2BaseURL, gcpBaseURL, digitalOceanBaseURL *url.URL + +func init() { + ec2BaseURL, _ = url.Parse("http://169.254.169.254/latest/meta-data") + gcpBaseURL, _ = url.Parse("http://metadata.google.internal/computeMetadata/v1") + digitalOceanBaseURL, _ = url.Parse("http://169.254.169.254/metadata/v1") // has not been yet used +} + // NewCloudGenerator creates a Cloud Generator instance with specified baseurl. func NewCloudGenerator(baseurl string) (*CloudGenerator, error) { if baseurl == "" { From b2f3598e866e8f23ae9aa1cfef0dca61fb4721e7 Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 17:57:10 +0900 Subject: [PATCH 05/18] fix interface of CloudGenerator for supporting another cloud provider --- spec/cloud.go | 35 +++++++++++++++++++++++------------ spec/cloud_test.go | 14 -------------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/spec/cloud.go b/spec/cloud.go index 912847c3f..955ac8554 100644 --- a/spec/cloud.go +++ b/spec/cloud.go @@ -17,7 +17,11 @@ import ( // CloudGenerator definition type CloudGenerator struct { - baseURL *url.URL + CloudSpecGenerator +} + +type CloudSpecGenerator interface { + Generate() (interface{}, error) } // Key is a root key for the generator. @@ -27,30 +31,37 @@ func (g *CloudGenerator) Key() string { var cloudLogger = logging.GetLogger("spec.cloud") -var ec2BaseURL, gcpBaseURL, digitalOceanBaseURL *url.URL +const ( + ec2BaseURL = "http://169.254.169.254/latest/meta-data" + gcpBaseURL = "http://metadata.google.internal/computeMetadata/v1" + digitalOceanBaseURL = "http://169.254.169.254/metadata/v1" // has not been yet used +) -func init() { - ec2BaseURL, _ = url.Parse("http://169.254.169.254/latest/meta-data") - gcpBaseURL, _ = url.Parse("http://metadata.google.internal/computeMetadata/v1") - digitalOceanBaseURL, _ = url.Parse("http://169.254.169.254/metadata/v1") // has not been yet used -} +var timeout = 100 * time.Millisecond // NewCloudGenerator creates a Cloud Generator instance with specified baseurl. func NewCloudGenerator(baseurl string) (*CloudGenerator, error) { if baseurl == "" { - baseurl = "http://169.254.169.254/latest/meta-data" + baseurl = ec2BaseURL } u, err := url.Parse(baseurl) if err != nil { return nil, err } - return &CloudGenerator{u}, nil + return &CloudGenerator{&EC2Generator{u}}, nil } -// Generate collects metadata from cloud platform. -func (g *CloudGenerator) Generate() (interface{}, error) { +type EC2Generator struct { + baseURL *url.URL +} - timeout := time.Duration(100 * time.Millisecond) +func NewEC2Generator() *EC2Generator { + url, _ := url.Parse(ec2BaseURL) + return &EC2Generator{url} +} + +// Generate collects metadata from cloud platform. +func (g *EC2Generator) Generate() (interface{}, error) { client := http.Client{ Timeout: timeout, } diff --git a/spec/cloud_test.go b/spec/cloud_test.go index 7620b60fc..93aa2455c 100644 --- a/spec/cloud_test.go +++ b/spec/cloud_test.go @@ -7,20 +7,6 @@ import ( "testing" ) -func TestNewCloudGenerator(t *testing.T) { - g, err := NewCloudGenerator( - "http://example.com", - ) - - if err != nil { - t.Errorf("should not raise error: %v", err) - } - - if g.baseURL.String() != "http://example.com" { - t.Error("should return URL") - } -} - func TestCloudKey(t *testing.T) { g := &CloudGenerator{} From 82d24c261faf444b882d68dac203b22239637fcf Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 18:18:12 +0900 Subject: [PATCH 06/18] define SuggestCloudGenerator() --- spec/cloud.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/spec/cloud.go b/spec/cloud.go index 955ac8554..632e21058 100644 --- a/spec/cloud.go +++ b/spec/cloud.go @@ -39,6 +39,22 @@ const ( var timeout = 100 * time.Millisecond +// SuggestCloudGenerator returns suitable CloudGenerator +func SuggestCloudGenerator() *CloudGenerator { + cl := http.Client{ + Timeout: timeout, + } + + // '/ami-id` is may be aws specific URL + resp, err := cl.Get(ec2BaseURL + "/ami-id") + if err == nil { + resp.Body.Close() + return &CloudGenerator{NewEC2Generator()} + } + + return nil +} + // NewCloudGenerator creates a Cloud Generator instance with specified baseurl. func NewCloudGenerator(baseurl string) (*CloudGenerator, error) { if baseurl == "" { From 0336ff30344043d426470ee68d45763711edfa6c Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 18:39:48 +0900 Subject: [PATCH 07/18] use SuggestCloudGenerator() --- command/command.go | 7 ++++++- command/command_freebsd.go | 9 +-------- command/command_linux.go | 9 +-------- command/command_windows.go | 9 +-------- 4 files changed, 9 insertions(+), 25 deletions(-) diff --git a/command/command.go b/command/command.go index 21a80209a..c498d68ce 100644 --- a/command/command.go +++ b/command/command.go @@ -475,7 +475,12 @@ func collectHostSpecs() (string, map[string]interface{}, []map[string]interface{ return "", nil, nil, fmt.Errorf("failed to obtain hostname: %s", err.Error()) } - meta := spec.Collect(specGenerators()) + specGens := specGenerators() + cGen := spec.SuggestCloudGenerator() + if cGen != nil { + specGens = append(specGens, cGen) + } + meta := spec.Collect(specGens) interfacesSpec, err := interfaceGenerator().Generate() if err != nil { diff --git a/command/command_freebsd.go b/command/command_freebsd.go index 538e818c4..76a4e45d1 100644 --- a/command/command_freebsd.go +++ b/command/command_freebsd.go @@ -9,19 +9,12 @@ import ( ) func specGenerators() []spec.Generator { - specs := []spec.Generator{ + return []spec.Generator{ &specFreebsd.KernelGenerator{}, &specFreebsd.MemoryGenerator{}, &specFreebsd.CPUGenerator{}, &specFreebsd.FilesystemGenerator{}, } - cloudGenerator, err := spec.NewCloudGenerator("") - if err != nil { - logger.Errorf("Failed to create cloudGenerator: %s", err.Error()) - } else { - specs = append(specs, cloudGenerator) - } - return specs } func interfaceGenerator() spec.Generator { diff --git a/command/command_linux.go b/command/command_linux.go index c4627ee7a..5920a12c6 100644 --- a/command/command_linux.go +++ b/command/command_linux.go @@ -9,20 +9,13 @@ import ( ) func specGenerators() []spec.Generator { - specs := []spec.Generator{ + return []spec.Generator{ &specLinux.KernelGenerator{}, &specLinux.CPUGenerator{}, &specLinux.MemoryGenerator{}, &specLinux.BlockDeviceGenerator{}, &specLinux.FilesystemGenerator{}, } - cloudGenerator, err := spec.NewCloudGenerator("") - if err != nil { - logger.Errorf("Failed to create cloudGenerator: %s", err.Error()) - } else { - specs = append(specs, cloudGenerator) - } - return specs } func interfaceGenerator() spec.Generator { diff --git a/command/command_windows.go b/command/command_windows.go index 4672e4650..5585e406f 100644 --- a/command/command_windows.go +++ b/command/command_windows.go @@ -9,20 +9,13 @@ import ( ) func specGenerators() []spec.Generator { - specs := []spec.Generator{ + return []spec.Generator{ &specWindows.KernelGenerator{}, &specWindows.CPUGenerator{}, &specWindows.MemoryGenerator{}, &specWindows.BlockDeviceGenerator{}, &specWindows.FilesystemGenerator{}, } - cloudGenerator, err := spec.NewCloudGenerator("") - if err != nil { - logger.Errorf("Failed to create cloudGenerator: %s", err.Error()) - } else { - specs = append(specs, cloudGenerator) - } - return specs } func interfaceGenerator() spec.Generator { From 2f69680126ddf8c4cbc24ccd0540e0510aa52dba Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 19:24:43 +0900 Subject: [PATCH 08/18] s/CloudSpecGenerator/CloudMetaGenerator/g --- spec/cloud.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/cloud.go b/spec/cloud.go index 632e21058..ae9b1733f 100644 --- a/spec/cloud.go +++ b/spec/cloud.go @@ -17,10 +17,10 @@ import ( // CloudGenerator definition type CloudGenerator struct { - CloudSpecGenerator + CloudMetaGenerator } -type CloudSpecGenerator interface { +type CloudMetaGenerator interface { Generate() (interface{}, error) } From e6f43afaba5bb81bb30982a9271659fb5c0b2f88 Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 19:43:44 +0900 Subject: [PATCH 09/18] remove NewCloudGenerator() which no longer used --- spec/cloud.go | 12 ------------ spec/cloud_test.go | 5 ++++- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/spec/cloud.go b/spec/cloud.go index ae9b1733f..79fb738f6 100644 --- a/spec/cloud.go +++ b/spec/cloud.go @@ -55,18 +55,6 @@ func SuggestCloudGenerator() *CloudGenerator { return nil } -// NewCloudGenerator creates a Cloud Generator instance with specified baseurl. -func NewCloudGenerator(baseurl string) (*CloudGenerator, error) { - if baseurl == "" { - baseurl = ec2BaseURL - } - u, err := url.Parse(baseurl) - if err != nil { - return nil, err - } - return &CloudGenerator{&EC2Generator{u}}, nil -} - type EC2Generator struct { baseURL *url.URL } diff --git a/spec/cloud_test.go b/spec/cloud_test.go index 93aa2455c..c4312faa4 100644 --- a/spec/cloud_test.go +++ b/spec/cloud_test.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "net/url" "testing" ) @@ -24,10 +25,12 @@ func TestCloudGenerate(t *testing.T) { })) defer ts.Close() - g, err := NewCloudGenerator(ts.URL) + u, err := url.Parse(ts.URL) if err != nil { t.Errorf("should not raise error: %s", err) } + g := &CloudGenerator{&EC2Generator{u}} + value, err := g.Generate() if err != nil { t.Errorf("should not raise error: %s", err) From 0bd3224b03075f128ad741fae8058778c63122b7 Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 20:08:24 +0900 Subject: [PATCH 10/18] add comment --- spec/cloud.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/cloud.go b/spec/cloud.go index 79fb738f6..b46059c10 100644 --- a/spec/cloud.go +++ b/spec/cloud.go @@ -20,6 +20,7 @@ type CloudGenerator struct { CloudMetaGenerator } +// CloudMetaGenerator interface of metadata generator for each cloud platform type CloudMetaGenerator interface { Generate() (interface{}, error) } @@ -55,10 +56,12 @@ func SuggestCloudGenerator() *CloudGenerator { return nil } +// EC2Generator meta generator for EC2 type EC2Generator struct { baseURL *url.URL } +// NewEC2Generator returns new instance of EC2Generator func NewEC2Generator() *EC2Generator { url, _ := url.Parse(ec2BaseURL) return &EC2Generator{url} From 38fa40b81d153956f3ae30a06f0423811eb1b068 Mon Sep 17 00:00:00 2001 From: Songmu Date: Sun, 12 Jul 2015 20:53:16 +0900 Subject: [PATCH 11/18] define isEC2() and refactor --- spec/cloud.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/spec/cloud.go b/spec/cloud.go index b46059c10..bfb7ed449 100644 --- a/spec/cloud.go +++ b/spec/cloud.go @@ -42,18 +42,28 @@ var timeout = 100 * time.Millisecond // SuggestCloudGenerator returns suitable CloudGenerator func SuggestCloudGenerator() *CloudGenerator { + if isEC2() { + return &CloudGenerator{NewEC2Generator()} + } + + return nil +} + +func isEC2() bool { cl := http.Client{ Timeout: timeout, } - // '/ami-id` is may be aws specific URL resp, err := cl.Get(ec2BaseURL + "/ami-id") - if err == nil { - resp.Body.Close() - return &CloudGenerator{NewEC2Generator()} + if err != nil { + return false } + defer resp.Body.Close() - return nil + if resp.StatusCode == 200 { + return true + } + return false } // EC2Generator meta generator for EC2 From 309327e1ca0b218292533b186a08e60cbf8cd42f Mon Sep 17 00:00:00 2001 From: Songmu Date: Mon, 13 Jul 2015 02:33:04 +0900 Subject: [PATCH 12/18] remove `UpdateHost()` process from `prepareHost()` for simplicity --- command/command.go | 20 +++----------------- command/command_test.go | 5 +++++ 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/command/command.go b/command/command.go index 21a80209a..e503ce1a1 100644 --- a/command/command.go +++ b/command/command.go @@ -108,7 +108,7 @@ func prepareHost(root string, api *mackerel.API, roleFullnames []string, checks if lastErr != nil { return nil, fmt.Errorf("Failed to find this host on mackerel: %s", lastErr.Error()) } - } else { // update + } else { // check the hostID is valid or not doRetry(func() error { result, lastErr = api.FindHost(hostID) return filterErrorForRetry(lastErr) @@ -116,21 +116,6 @@ func prepareHost(root string, api *mackerel.API, roleFullnames []string, checks if lastErr != nil { return nil, fmt.Errorf("Failed to find this host on mackerel (You may want to delete file \"%s\" to register this host to an another organization): %s", idFilePath(root), lastErr.Error()) } - - doRetry(func() error { - lastErr = api.UpdateHost(hostID, mackerel.HostSpec{ - Name: hostname, - Meta: meta, - Interfaces: interfaces, - RoleFullnames: roleFullnames, - Checks: checks, - DisplayName: displayName, - }) - return filterErrorForRetry(lastErr) - }) - if lastErr != nil { - return nil, fmt.Errorf("Failed to update this host: %s", lastErr.Error()) - } } if hostSt != "" && hostSt != result.Status { @@ -321,11 +306,12 @@ func loop(c *context, termCh chan struct{}) int { func updateHostSpecsLoop(c *context, quit chan struct{}) { for { + UpdateHostSpecs(c.conf, c.api, c.host) select { case <-quit: return case <-time.After(specsUpdateInterval): - UpdateHostSpecs(c.conf, c.api, c.host) + // nop } } } diff --git a/command/command_test.go b/command/command_test.go index a00e98f7f..d1a34713e 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -284,6 +284,11 @@ func TestLoop(t *testing.T) { "success": true, } } + mockHandlers["PUT /api/v0/hosts/xyzabc12345"] = func(req *http.Request) (int, jsonObject) { + return 200, jsonObject{ + "result": "OK", + } + } // Prepare required objects... ag := &agent.Agent{ From 488154ab62ee26777b8407661448240a32071354 Mon Sep 17 00:00:00 2001 From: Songmu Date: Mon, 13 Jul 2015 22:59:05 +0900 Subject: [PATCH 13/18] filter invalid roleFullNames with warning logs --- main.go | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/main.go b/main.go index f8b77c944..d8e32990c 100644 --- a/main.go +++ b/main.go @@ -22,7 +22,7 @@ import ( // allow options like -role=... -role=... type roleFullnamesFlag []string -var roleFullnamePattern = regexp.MustCompile(`^[\w-]+:\s*[\w-]+$`) +var roleFullnamePattern = regexp.MustCompile(`^[a-zA-Z0-9][-_a-zA-Z0-9]*:\s*[a-zA-Z0-9][-_a-zA-Z0-9]*$`) func (r *roleFullnamesFlag) String() string { return fmt.Sprint(*r) @@ -30,15 +30,7 @@ func (r *roleFullnamesFlag) String() string { func (r *roleFullnamesFlag) Set(input string) error { inputRoles := strings.Split(input, ",") - - for _, inputRole := range inputRoles { - if roleFullnamePattern.MatchString(inputRole) == false { - return fmt.Errorf("Bad format for role fullname (expecting :): %s", inputRole) - } - } - *r = append(*r, inputRoles...) - return nil } @@ -88,14 +80,14 @@ func resolveConfig() (*config.Config, *otherOptions) { otherOptions := &otherOptions{} var ( - conffile = flag.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)") - apibase = flag.String("apibase", config.DefaultConfig.Apibase, "API base") - pidfile = flag.String("pidfile", config.DefaultConfig.Pidfile, "File containing PID") - root = flag.String("root", config.DefaultConfig.Root, "Directory containing variable state information") - apikey = flag.String("apikey", "", "API key from mackerel.io web site") - diagnostic = flag.Bool("diagnostic", false, "Enables diagnostic features") - runOnce = flag.Bool("once", false, "Show spec and metrics to stdout once") - printVersion = flag.Bool("version", false, "Prints version and exit") + conffile = flag.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)") + apibase = flag.String("apibase", config.DefaultConfig.Apibase, "API base") + pidfile = flag.String("pidfile", config.DefaultConfig.Pidfile, "File containing PID") + root = flag.String("root", config.DefaultConfig.Root, "Directory containing variable state information") + apikey = flag.String("apikey", "", "API key from mackerel.io web site") + diagnostic = flag.Bool("diagnostic", false, "Enables diagnostic features") + runOnce = flag.Bool("once", false, "Show spec and metrics to stdout once") + printVersion = flag.Bool("version", false, "Prints version and exit") ) var verbose bool @@ -145,6 +137,15 @@ func resolveConfig() (*config.Config, *otherOptions) { } }) + r := []string{} + for _, roleFullName := range conf.Roles { + if !roleFullnamePattern.MatchString(roleFullName) { + logger.Errorf("Bad format for role fullname (expecting :. Alphabet, numbers, hyphens and underscores are acceptable, but the first character must not be a hyphen or an underscore.): '%s'", roleFullName) + } else { + r = append(r, roleFullName) + } + } + conf.Roles = r return conf, nil } From 759a4a9f2d8fe96856c50f7b81a23782851cef7c Mon Sep 17 00:00:00 2001 From: Songmu Date: Tue, 14 Jul 2015 09:55:13 +0900 Subject: [PATCH 14/18] test of filter invalid rolefullname --- main_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main_test.go b/main_test.go index 7bcdf09d4..b3b2173e4 100644 --- a/main_test.go +++ b/main_test.go @@ -23,7 +23,7 @@ diagnostic=false confFile.Close() defer os.Remove(confFile.Name()) - os.Args = []string{"mackerel-agent", "-conf=" + confFile.Name(), "-role=My-Service:default", "-verbose", "-diagnostic"} + os.Args = []string{"mackerel-agent", "-conf=" + confFile.Name(), "-role=My-Service:default,INVALID#SERVICE", "-verbose", "-diagnostic"} // Overrides Args from go test command flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.PanicOnError) From 25539b260c708f082e3ce79dd4bb53792f4baffb Mon Sep 17 00:00:00 2001 From: Songmu Date: Wed, 15 Jul 2015 20:17:33 +0900 Subject: [PATCH 15/18] allow using spaces as delimiter for split custom metric values --- metrics/plugin.go | 4 ++- .../{plugin_linux_test.go => plugin_test.go} | 26 ++++++++++++++++++- metrics/windows/plugin.go | 5 +++- 3 files changed, 32 insertions(+), 3 deletions(-) rename metrics/{plugin_linux_test.go => plugin_test.go} (89%) diff --git a/metrics/plugin.go b/metrics/plugin.go index 97a000c49..6d551c5a7 100644 --- a/metrics/plugin.go +++ b/metrics/plugin.go @@ -212,6 +212,8 @@ func (g *pluginGenerator) makeCreateGraphDefsPayload() []mackerel.CreateGraphDef return payloads } +var delimReg = regexp.MustCompile(`[\s\t]+`) + func (g *pluginGenerator) collectValues() (Values, error) { command := g.Config.Command pluginLogger.Debugf("Executing plugin: command = \"%s\"", command) @@ -228,7 +230,7 @@ func (g *pluginGenerator) collectValues() (Values, error) { for _, line := range strings.Split(stdout, "\n") { // Key, value, timestamp // ex.) tcp.CLOSING 0 1397031808 - items := strings.Split(line, "\t") + items := delimReg.Split(line, 3) if len(items) != 3 { continue } diff --git a/metrics/plugin_linux_test.go b/metrics/plugin_test.go similarity index 89% rename from metrics/plugin_linux_test.go rename to metrics/plugin_test.go index 8dfe6aa03..cb94b48a5 100644 --- a/metrics/plugin_linux_test.go +++ b/metrics/plugin_test.go @@ -1,4 +1,4 @@ -// +build linux +// +build linux darwin freebsd package metrics @@ -73,6 +73,30 @@ func TestPluginCollectValuesCommand(t *testing.T) { } } +func TestPluginCollectValuesCommandWithSpaces(t *testing.T) { + g := &pluginGenerator{Config: config.PluginConfig{ + Command: `echo "just.echo.2 2 1397822016"`, + }} + + values, err := g.collectValues() + if err != nil { + t.Errorf("should not raise error: %v", err) + } + + if len(values) != 1 { + t.Error("Only 1 value shoud be generated") + } + + for name, value := range values { + if name != "custom.just.echo.2" { + t.Errorf("Wrong name: %s", name) + } + if value != 2.0 { + t.Errorf("Wrong value: %+v", value) + } + } +} + func TestPluginLoadPluginMeta(t *testing.T) { g := &pluginGenerator{ Config: config.PluginConfig{ diff --git a/metrics/windows/plugin.go b/metrics/windows/plugin.go index 26cf1fc68..fcc5aa414 100644 --- a/metrics/windows/plugin.go +++ b/metrics/windows/plugin.go @@ -6,6 +6,7 @@ import ( "bytes" "errors" "os/exec" + "regexp" "strconv" "strings" @@ -43,6 +44,8 @@ func (g *PluginGenerator) Generate() (metrics.Values, error) { return results, nil } +var delimReg = regexp.MustCompile(`[\s\t]+`) + func (g *PluginGenerator) collectValues(command string) (metrics.Values, error) { pluginLogger.Debugf("Executing plugin: command = \"%s\"", command) @@ -63,7 +66,7 @@ func (g *PluginGenerator) collectValues(command string) (metrics.Values, error) for _, line := range strings.Split(string(outBuffer.Bytes()), "\n") { // Key, value, timestamp // ex.) localhost.localdomain.tcp.CLOSING 0 1397031808 - items := strings.Split(line, "\t") + items := delimReg.Split(line, 3) if len(items) != 3 { continue } From f560b57fe5e5c322c686170e9c59630c1af0b4ad Mon Sep 17 00:00:00 2001 From: Songmu Date: Wed, 15 Jul 2015 21:59:34 +0900 Subject: [PATCH 16/18] trivial fix --- spec/cloud.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/spec/cloud.go b/spec/cloud.go index bfb7ed449..03a734254 100644 --- a/spec/cloud.go +++ b/spec/cloud.go @@ -60,10 +60,7 @@ func isEC2() bool { } defer resp.Body.Close() - if resp.StatusCode == 200 { - return true - } - return false + return resp.StatusCode == 200 } // EC2Generator meta generator for EC2 From 316a9b8ea980cf21003de3636820774c4b90fc88 Mon Sep 17 00:00:00 2001 From: Songmu Date: Thu, 16 Jul 2015 17:05:42 +0900 Subject: [PATCH 17/18] ready for next release. version: 0.18.1 --- .travis.yml | 4 ++-- packaging/rpm/mackerel-agent.spec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index f0a7b4e57..48e736d62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,8 +22,8 @@ deploy: api_key: secure: NtpNjquqjnwpeVQQM1GTHTTU7YOo8fEIyoBtMf3Vf1ayZjuWVZxwNfM77E596TG52a8pnZtpapXyHT0M4e1zms7F5KVCrOEfOB0OrA4IDzoATelVqdONnN3lbRJeVJVdSmK8/FNKwjI24tQZTaTQcIOioNqh7ZRcrEYlatGCuAw= file: - - /home/travis/rpmbuild/RPMS/noarch/mackerel-agent-0.18.0-1.noarch.rpm - - packaging/mackerel-agent_0.18.0-1_all.deb + - /home/travis/rpmbuild/RPMS/noarch/mackerel-agent-0.18.1-1.noarch.rpm + - packaging/mackerel-agent_0.18.1-1_all.deb - snapshot/mackerel-agent_darwin_386.zip - snapshot/mackerel-agent_darwin_amd64.zip - snapshot/mackerel-agent_freebsd_386.zip diff --git a/packaging/rpm/mackerel-agent.spec b/packaging/rpm/mackerel-agent.spec index 2b386e3a3..c3b104ca2 100644 --- a/packaging/rpm/mackerel-agent.spec +++ b/packaging/rpm/mackerel-agent.spec @@ -5,7 +5,7 @@ %define _localbindir /usr/local/bin Name: mackerel-agent -Version: 0.18.0 +Version: 0.18.1 Release: 1 License: Commercial Summary: macekrel.io agent From b04dcd9bb887d9a199a7e242ddc48b09ed970dc2 Mon Sep 17 00:00:00 2001 From: Songmu Date: Thu, 16 Jul 2015 17:05:43 +0900 Subject: [PATCH 18/18] update changelogs --- CHANGELOG.md | 8 ++++++++ packaging/deb/debian/changelog | 13 +++++++++++++ packaging/rpm/mackerel-agent.spec | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f9c50bf7..c6a8ae776 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.18.1 (2015-07-16) + +* s/ami_id/ami-id/ in spec/cloud.go #112 (Songmu) +* remove `UpdateHost()` process from `prepareHost()` for simplicity #116 (Songmu) +* filter invalid roleFullNames with warning logs #117 (Songmu) +* allow using spaces as delimiter for custom metric values #119 (Songmu) + + ## 0.18.0 (2015-07-08) * Retry in prepare #108 (Songmu) diff --git a/packaging/deb/debian/changelog b/packaging/deb/debian/changelog index 4deb05d25..f5cddd663 100644 --- a/packaging/deb/debian/changelog +++ b/packaging/deb/debian/changelog @@ -1,3 +1,16 @@ +mackerel-agent (0.18.1-1) stable; urgency=low + + * s/ami_id/ami-id/ in spec/cloud.go (by Songmu) + + * remove `UpdateHost()` process from `prepareHost()` for simplicity (by Songmu) + + * filter invalid roleFullNames with warning logs (by Songmu) + + * allow using spaces as delimiter for custom metric values (by Songmu) + + + -- Songmu Thu, 16 Jul 2015 17:05:43 +0900 + mackerel-agent (0.18.0-1) stable; urgency=low * Retry in prepare (by Songmu) diff --git a/packaging/rpm/mackerel-agent.spec b/packaging/rpm/mackerel-agent.spec index c3b104ca2..161a317fb 100644 --- a/packaging/rpm/mackerel-agent.spec +++ b/packaging/rpm/mackerel-agent.spec @@ -73,6 +73,12 @@ fi %{_sysconfdir}/logrotate.d/%{name} %changelog +* Thu Jul 16 2015 - 0.18.1-1 +- s/ami_id/ami-id/ in spec/cloud.go (by Songmu) +- remove `UpdateHost()` process from `prepareHost()` for simplicity (by Songmu) +- filter invalid roleFullNames with warning logs (by Songmu) +- allow using spaces as delimiter for custom metric values (by Songmu) + * Wed Jul 08 2015 - 0.18.0-1 - Retry in prepare (by Songmu) - [WORKAROUND] downgrade golang version for windows (by Sixeight)