-
Notifications
You must be signed in to change notification settings - Fork 22
/
exact_version.go
153 lines (127 loc) · 3.46 KB
/
exact_version.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package releases
import (
"context"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"time"
"github.com/hashicorp/go-version"
"github.com/hashicorp/hc-install/internal/pubkey"
rjson "github.com/hashicorp/hc-install/internal/releasesjson"
isrc "github.com/hashicorp/hc-install/internal/src"
"github.com/hashicorp/hc-install/internal/validators"
"github.com/hashicorp/hc-install/product"
)
// ExactVersion installs the given Version of product
// to OS temp directory, or to InstallDir (if not empty)
type ExactVersion struct {
Product product.Product
Version *version.Version
InstallDir string
Timeout time.Duration
SkipChecksumVerification bool
// ArmoredPublicKey is a public PGP key in ASCII/armor format to use
// instead of built-in pubkey to verify signature of downloaded checksums
ArmoredPublicKey string
apiBaseURL string
logger *log.Logger
pathsToRemove []string
}
func (*ExactVersion) IsSourceImpl() isrc.InstallSrcSigil {
return isrc.InstallSrcSigil{}
}
func (ev *ExactVersion) SetLogger(logger *log.Logger) {
ev.logger = logger
}
func (ev *ExactVersion) log() *log.Logger {
if ev.logger == nil {
return discardLogger
}
return ev.logger
}
func (ev *ExactVersion) Validate() error {
if !validators.IsProductNameValid(ev.Product.Name) {
return fmt.Errorf("invalid product name: %q", ev.Product.Name)
}
if !validators.IsBinaryNameValid(ev.Product.BinaryName()) {
return fmt.Errorf("invalid binary name: %q", ev.Product.BinaryName())
}
if ev.Version == nil {
return fmt.Errorf("unknown version")
}
return nil
}
func (ev *ExactVersion) Install(ctx context.Context) (string, error) {
timeout := defaultInstallTimeout
if ev.Timeout > 0 {
timeout = ev.Timeout
}
ctx, cancelFunc := context.WithTimeout(ctx, timeout)
defer cancelFunc()
if ev.pathsToRemove == nil {
ev.pathsToRemove = make([]string, 0)
}
dstDir := ev.InstallDir
if dstDir == "" {
var err error
dirName := fmt.Sprintf("%s_*", ev.Product.Name)
dstDir, err = ioutil.TempDir("", dirName)
if err != nil {
return "", err
}
ev.pathsToRemove = append(ev.pathsToRemove, dstDir)
ev.log().Printf("created new temp dir at %s", dstDir)
}
ev.log().Printf("will install into dir at %s", dstDir)
rels := rjson.NewReleases()
if ev.apiBaseURL != "" {
rels.BaseURL = ev.apiBaseURL
}
rels.SetLogger(ev.log())
pv, err := rels.GetProductVersion(ctx, ev.Product.Name, ev.Version)
if err != nil {
return "", err
}
d := &rjson.Downloader{
Logger: ev.log(),
VerifyChecksum: !ev.SkipChecksumVerification,
ArmoredPublicKey: pubkey.DefaultPublicKey,
BaseURL: rels.BaseURL,
}
if ev.ArmoredPublicKey != "" {
d.ArmoredPublicKey = ev.ArmoredPublicKey
}
if ev.apiBaseURL != "" {
d.BaseURL = ev.apiBaseURL
}
zipFilePath, err := d.DownloadAndUnpack(ctx, pv, dstDir)
if zipFilePath != "" {
ev.pathsToRemove = append(ev.pathsToRemove, zipFilePath)
}
if err != nil {
return "", err
}
execPath := filepath.Join(dstDir, ev.Product.BinaryName())
ev.pathsToRemove = append(ev.pathsToRemove, execPath)
ev.log().Printf("changing perms of %s", execPath)
err = os.Chmod(execPath, 0o700)
if err != nil {
return "", err
}
return execPath, nil
}
func (ev *ExactVersion) Remove(ctx context.Context) error {
if ev.pathsToRemove != nil {
for _, path := range ev.pathsToRemove {
err := os.RemoveAll(path)
if err != nil {
return err
}
}
}
return nil
}