From f9b00ac05eb66433bf3c64e0409f84f76ce1a8f7 Mon Sep 17 00:00:00 2001 From: Blake Rouse Date: Mon, 29 Jun 2020 09:05:58 -0400 Subject: [PATCH 1/2] Handle the migration from agent_info to agent. --- .../pkg/agent/application/info/agent_id.go | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/x-pack/elastic-agent/pkg/agent/application/info/agent_id.go b/x-pack/elastic-agent/pkg/agent/application/info/agent_id.go index e0b3bf3e840a..2b3654f11a61 100644 --- a/x-pack/elastic-agent/pkg/agent/application/info/agent_id.go +++ b/x-pack/elastic-agent/pkg/agent/application/info/agent_id.go @@ -21,13 +21,15 @@ import ( // defaultAgentConfigFile is a name of file used to store agent information const defaultAgentConfigFile = "fleet.yml" -const agentInfoKey = "agent" +const agentInfoKey = "agent_info" +const agentKey = "agent" // defaultAgentActionStoreFile is the file that will contains the action that can be replayed after restart. const defaultAgentActionStoreFile = "action_store.yml" type persistentAgentInfo struct { - ID string `json:"id" yaml:"id" config:"id"` + ID string `json:"id" yaml:"id" config:"id"` + CapID string `json:"ID,omitempty" yaml:"ID,omitempty" config:"ID"` } type ioStore interface { @@ -105,9 +107,13 @@ func getInfoFromStore(s ioStore) (*persistentAgentInfo, error) { errors.TypeFilesystem) } - agentInfoSubMap, found := configMap[agentInfoKey] + // handle migration of `agent_info` to `agent` in config + agentInfoSubMap, found := configMap[agentKey] if !found { - return &persistentAgentInfo{}, nil + agentInfoSubMap, found = configMap[agentInfoKey] + if !found { + return &persistentAgentInfo{}, nil + } } cc, err := config.NewConfigFrom(agentInfoSubMap) @@ -120,6 +126,12 @@ func getInfoFromStore(s ioStore) (*persistentAgentInfo, error) { return nil, errors.New(err, "failed to unpack stored config to map") } + // handle migration of agent ID from `ID` to `id` in YAML. + if pid.ID == "" && pid.CapID != "" { + pid.ID = pid.CapID + pid.CapID = "" + } + return pid, nil } @@ -146,7 +158,15 @@ func updateAgentInfo(s ioStore, agentInfo *persistentAgentInfo) error { return errors.New(err, "failed to unpack stored config to map") } - configMap[agentInfoKey] = agentInfo + // handle migration of agent ID from `ID` to `id` in YAML. + if agentInfo.ID == "" && agentInfo.CapID != "" { + agentInfo.ID = agentInfo.CapID + agentInfo.CapID = "" + } + + // set `agent` and remove old `agent_info` + configMap[agentKey] = agentInfo + delete(configMap, agentInfoKey) r, err := yamlToReader(configMap) if err != nil { From c8ea0477e6357e2e07b08be0e5731a7ae202c6b8 Mon Sep 17 00:00:00 2001 From: Blake Rouse Date: Mon, 29 Jun 2020 09:31:45 -0400 Subject: [PATCH 2/2] Add testing and changelog. --- x-pack/elastic-agent/CHANGELOG.asciidoc | 1 + .../agent/application/info/agent_id_test.go | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 x-pack/elastic-agent/pkg/agent/application/info/agent_id_test.go diff --git a/x-pack/elastic-agent/CHANGELOG.asciidoc b/x-pack/elastic-agent/CHANGELOG.asciidoc index c66798a01da4..500e90d308db 100644 --- a/x-pack/elastic-agent/CHANGELOG.asciidoc +++ b/x-pack/elastic-agent/CHANGELOG.asciidoc @@ -73,3 +73,4 @@ - Agent now runs the GRPC server and spawned application connect by to Agent {pull}18973[18973] - Rename input.type logs to logfile {pull}19360[19360] - Agent now installs/uninstalls Elastic Endpoint {pull}19248[19248] +- Handle upgrade of Fleet.yml format transparently {pull}19488[19488] diff --git a/x-pack/elastic-agent/pkg/agent/application/info/agent_id_test.go b/x-pack/elastic-agent/pkg/agent/application/info/agent_id_test.go new file mode 100644 index 000000000000..0e421e817911 --- /dev/null +++ b/x-pack/elastic-agent/pkg/agent/application/info/agent_id_test.go @@ -0,0 +1,75 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package info + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/storage" +) + +func TestLoadAgentInfo(t *testing.T) { + defer cleanupFile() + + agentInfo, err := loadAgentInfo(false) + require.NoError(t, err) + assert.NotEqual(t, "", agentInfo.ID) + assert.Equal(t, "", agentInfo.CapID) +} + +func TestLoadAgentInfoForce(t *testing.T) { + defer cleanupFile() + + agentInfo, err := loadAgentInfo(false) + require.NoError(t, err) + assert.NotEqual(t, "", agentInfo.ID) + assert.Equal(t, "", agentInfo.CapID) + + agentInfo2, err := loadAgentInfo(true) + require.NoError(t, err) + assert.NotEqual(t, agentInfo.ID, agentInfo2.ID) +} + +func TestLoadAgentInfoUpgrade(t *testing.T) { + defer cleanupFile() + + // write an old agent info + agentConfigFile := AgentConfigFile() + s := storage.NewEncryptedDiskStore(agentConfigFile, []byte("")) + id, err := generateAgentID() + require.NoError(t, err) + err = writeOldAgentInfo(s, id) + require.NoError(t, err) + + // load agent info, will handle upgrade + agentInfo, err := loadAgentInfo(false) + require.NoError(t, err) + assert.Equal(t, id, agentInfo.ID) + assert.Equal(t, "", agentInfo.CapID) +} + +func cleanupFile() { + os.Remove(AgentConfigFile()) +} + +func writeOldAgentInfo(s ioStore, id string) error { + configMap := make(map[string]interface{}) + configMap[agentInfoKey] = struct { + ID string `json:"ID" yaml:"ID" config:"ID"` + }{ + ID: id, + } + + r, err := yamlToReader(configMap) + if err != nil { + return err + } + + return s.Save(r) +}