Skip to content

Commit 3880bd8

Browse files
committed
Introduce install descriptor
1 parent 93c55ba commit 3880bd8

File tree

3 files changed

+149
-4
lines changed

3 files changed

+149
-4
lines changed

internal/pkg/agent/application/upgrade/upgrade.go

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"strings"
1717
"time"
1818

19-
"github.com/otiai10/copy"
19+
filecopy "github.com/otiai10/copy"
2020
"go.elastic.co/apm/v2"
2121

2222
"github.com/elastic/elastic-agent/internal/pkg/agent/application/filelock"
@@ -34,6 +34,7 @@ import (
3434
"github.com/elastic/elastic-agent/internal/pkg/fleetapi/acker"
3535
fleetclient "github.com/elastic/elastic-agent/internal/pkg/fleetapi/client"
3636
"github.com/elastic/elastic-agent/internal/pkg/release"
37+
v1 "github.com/elastic/elastic-agent/pkg/api/v1"
3738
"github.com/elastic/elastic-agent/pkg/control/v2/client"
3839
"github.com/elastic/elastic-agent/pkg/control/v2/cproto"
3940
"github.com/elastic/elastic-agent/pkg/core/logger"
@@ -358,6 +359,9 @@ func (u *Upgrader) Upgrade(ctx context.Context, version string, rollback bool, s
358359
return nil, err
359360
}
360361

362+
//FIXME make it nicer
363+
err = addInstallDesc(version, unpackRes.VersionedHome, unpackRes.Hash, detectedFlavor)
364+
361365
newHash := unpackRes.Hash
362366
if newHash == "" {
363367
return nil, errors.New("unknown hash")
@@ -457,6 +461,65 @@ func (u *Upgrader) Upgrade(ctx context.Context, version string, rollback bool, s
457461
return cb, nil
458462
}
459463

464+
func addInstallDesc(version string, home string, hash string, flavor string) error {
465+
installMarkerFilePath := filepath.Join(paths.Top(), paths.MarkerFileName)
466+
installDescriptor, err := readInstallMarker(installMarkerFilePath)
467+
if err != nil {
468+
return err
469+
}
470+
471+
if installDescriptor == nil {
472+
return fmt.Errorf("no install descriptor found at %q")
473+
}
474+
475+
existingInstalls := installDescriptor.AgentInstalls
476+
installDescriptor.AgentInstalls = make([]v1.AgentInstallDesc, len(existingInstalls)+1)
477+
newInstall := v1.AgentInstallDesc{
478+
Version: version,
479+
Hash: hash,
480+
VersionedHome: home,
481+
Flavor: flavor,
482+
}
483+
installDescriptor.AgentInstalls[0] = newInstall
484+
copied := copy(installDescriptor.AgentInstalls[1:], existingInstalls)
485+
if copied != len(existingInstalls) {
486+
return fmt.Errorf("error adding new install %v to existing installs %v", newInstall, existingInstalls)
487+
}
488+
489+
err = writeInstallMarker(installMarkerFilePath, installDescriptor)
490+
if err != nil {
491+
return fmt.Errorf("writing updated install marker: %w", err)
492+
}
493+
494+
return nil
495+
}
496+
497+
func writeInstallMarker(markerFilePath string, descriptor *v1.InstallDescriptor) error {
498+
installMarkerFile, err := os.Create(markerFilePath)
499+
if err != nil {
500+
return fmt.Errorf("opening install marker file: %w", err)
501+
}
502+
defer func(installMarkerFile *os.File) {
503+
_ = installMarkerFile.Close()
504+
}(installMarkerFile)
505+
return v1.WriteInstallDescriptor(installMarkerFile, descriptor)
506+
}
507+
508+
func readInstallMarker(markerFilePath string) (*v1.InstallDescriptor, error) {
509+
installMarkerFile, err := os.Open(markerFilePath)
510+
if err != nil {
511+
return nil, fmt.Errorf("opening install marker file: %w", err)
512+
}
513+
defer func(installMarkerFile *os.File) {
514+
_ = installMarkerFile.Close()
515+
}(installMarkerFile)
516+
installDescriptor, err := v1.ParseInstallDescriptor(installMarkerFile)
517+
if err != nil {
518+
return nil, fmt.Errorf("parsing install marker file: %w", err)
519+
}
520+
return installDescriptor, nil
521+
}
522+
460523
func (u *Upgrader) rollbackToPreviousVersion(ctx context.Context, topDir string, now time.Time, version string, action *fleetapi.ActionUpgrade) (reexec.ShutdownCallbackFn, error) {
461524
if version == "" {
462525
return nil, ErrEmptyRollbackVersion
@@ -814,9 +877,9 @@ func copyDir(l *logger.Logger, from, to string, ignoreErrs bool, fileDirCopy fil
814877
copyConcurrency = runtime.NumCPU() * 4
815878
}
816879

817-
return fileDirCopy(from, to, copy.Options{
818-
OnSymlink: func(_ string) copy.SymlinkAction {
819-
return copy.Shallow
880+
return fileDirCopy(from, to, filecopy.Options{
881+
OnSymlink: func(_ string) filecopy.SymlinkAction {
882+
return filecopy.Shallow
820883
},
821884
Sync: true,
822885
OnError: onErr,

pkg/api/v1/install.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License 2.0;
3+
// you may not use this file except in compliance with the Elastic License 2.0.
4+
5+
package v1
6+
7+
import (
8+
"io"
9+
"time"
10+
11+
"gopkg.in/yaml.v2"
12+
)
13+
14+
const (
15+
InstallDescriptorKind = "InstallDescriptor"
16+
)
17+
18+
type OptionalTTLItem struct {
19+
TTL *time.Time `yaml:"ttl,omitempty" json:"ttl,omitempty"`
20+
}
21+
22+
type AgentInstallDesc struct {
23+
OptionalTTLItem `yaml:",inline" json:",inline"`
24+
Version string `yaml:"version,omitempty" json:"version,omitempty"`
25+
Hash string `yaml:"hash,omitempty" json:"hash,omitempty"`
26+
VersionedHome string `yaml:"versionedHome,omitempty" json:"versionedHome,omitempty"`
27+
Flavor string `yaml:"flavor,omitempty" json:"flavor,omitempty"`
28+
}
29+
30+
type InstallDescriptor struct {
31+
apiObject `yaml:",inline"`
32+
AgentInstalls []AgentInstallDesc `yaml:"agentInstalls,omitempty" json:"agentInstalls,omitempty"`
33+
}
34+
35+
func NewInstallDescriptor() *InstallDescriptor {
36+
return &InstallDescriptor{
37+
apiObject: apiObject{
38+
Version: VERSION,
39+
Kind: InstallDescriptorKind,
40+
},
41+
}
42+
}
43+
44+
func ParseInstallDescriptor(r io.Reader) (*InstallDescriptor, error) {
45+
id := NewInstallDescriptor()
46+
err := yaml.NewDecoder(r).Decode(id)
47+
return id, err
48+
}
49+
50+
func WriteInstallDescriptor(w io.Writer, id *InstallDescriptor) error {
51+
return yaml.NewEncoder(w).Encode(id)
52+
}

pkg/utils/manifest/path_mapper.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License 2.0;
3+
// you may not use this file except in compliance with the Elastic License 2.0.
4+
5+
package manifest
6+
7+
import (
8+
"path"
9+
"strings"
10+
)
11+
12+
// PathMapper is a utility object that will help with File mappings specified in a v1/Manifest
13+
type PathMapper struct {
14+
mappings []map[string]string
15+
}
16+
17+
func (pm PathMapper) Map(packagePath string) string {
18+
for _, mapping := range pm.mappings {
19+
for pkgPath, mappedPath := range mapping {
20+
if strings.HasPrefix(packagePath, pkgPath) {
21+
return path.Join(mappedPath, packagePath[len(pkgPath):])
22+
}
23+
}
24+
}
25+
return packagePath
26+
}
27+
28+
func NewPathMapper(mappings []map[string]string) *PathMapper {
29+
return &PathMapper{mappings}
30+
}

0 commit comments

Comments
 (0)