Skip to content

Commit 00a38c4

Browse files
authored
[teleport-update] common MakeURL with ability to override BaseURL (#51383)
* Add templates for client tools auto-update download url * Change to base url setting by env MakeURL moved to common function to be general for both, agent and client tools * Reuse MakeURL moved to common package * Fix linter warning * Add common env variable to override base url * Remove template from interface * Make template exported Change a stale comment * Remove unused code
1 parent 14a4371 commit 00a38c4

27 files changed

+344
-343
lines changed

lib/autoupdate/agent/config.go

Lines changed: 20 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
package agent
2020

2121
import (
22-
"encoding/json"
2322
"errors"
2423
"fmt"
2524
"io/fs"
@@ -30,6 +29,8 @@ import (
3029
"github.com/google/renameio/v2"
3130
"github.com/gravitational/trace"
3231
"gopkg.in/yaml.v3"
32+
33+
"github.com/gravitational/teleport/lib/autoupdate"
3334
)
3435

3536
const (
@@ -59,8 +60,8 @@ type UpdateSpec struct {
5960
Proxy string `yaml:"proxy"`
6061
// Group specifies the update group identifier for the agent.
6162
Group string `yaml:"group,omitempty"`
62-
// URLTemplate for the Teleport tgz download URL.
63-
URLTemplate string `yaml:"url_template,omitempty"`
63+
// BaseURL is CDN base URL used for the Teleport tgz download URL.
64+
BaseURL string `yaml:"base_url,omitempty"`
6465
// Enabled controls whether auto-updates are enabled.
6566
Enabled bool `yaml:"enabled"`
6667
// Pinned controls whether the active_version is pinned.
@@ -84,13 +85,13 @@ type Revision struct {
8485
// Version is the version of Teleport.
8586
Version string `yaml:"version" json:"version"`
8687
// Flags describe the edition of Teleport.
87-
Flags InstallFlags `yaml:"flags,flow,omitempty" json:"flags,omitempty"`
88+
Flags autoupdate.InstallFlags `yaml:"flags,flow,omitempty" json:"flags,omitempty"`
8889
}
8990

9091
// NewRevision create a Revision.
9192
// If version is not set, no flags are returned.
9293
// This ensures that all Revisions without versions are zero-valued.
93-
func NewRevision(version string, flags InstallFlags) Revision {
94+
func NewRevision(version string, flags autoupdate.InstallFlags) Revision {
9495
if version != "" {
9596
return Revision{
9697
Version: version,
@@ -113,16 +114,16 @@ func NewRevisionFromDir(dir string) (Revision, error) {
113114
}
114115
switch flags := parts[1:]; len(flags) {
115116
case 2:
116-
if flags[1] != FlagFIPS.DirFlag() {
117+
if flags[1] != autoupdate.FlagFIPS.DirFlag() {
117118
break
118119
}
119-
out.Flags |= FlagFIPS
120+
out.Flags |= autoupdate.FlagFIPS
120121
fallthrough
121122
case 1:
122-
if flags[0] != FlagEnterprise.DirFlag() {
123+
if flags[0] != autoupdate.FlagEnterprise.DirFlag() {
123124
break
124125
}
125-
out.Flags |= FlagEnterprise
126+
out.Flags |= autoupdate.FlagEnterprise
126127
fallthrough
127128
case 0:
128129
return out, nil
@@ -135,11 +136,11 @@ func (r Revision) Dir() string {
135136
// Do not change the order of these statements.
136137
// Otherwise, installed versions will no longer match update.yaml.
137138
var suffix string
138-
if r.Flags&(FlagEnterprise|FlagFIPS) != 0 {
139-
suffix += "_" + FlagEnterprise.DirFlag()
139+
if r.Flags&(autoupdate.FlagEnterprise|autoupdate.FlagFIPS) != 0 {
140+
suffix += "_" + autoupdate.FlagEnterprise.DirFlag()
140141
}
141-
if r.Flags&FlagFIPS != 0 {
142-
suffix += "_" + FlagFIPS.DirFlag()
142+
if r.Flags&autoupdate.FlagFIPS != 0 {
143+
suffix += "_" + autoupdate.FlagFIPS.DirFlag()
143144
}
144145
return r.Version + suffix
145146
}
@@ -203,16 +204,16 @@ func validateConfigSpec(spec *UpdateSpec, override OverrideConfig) error {
203204
if override.Group != "" {
204205
spec.Group = override.Group
205206
}
206-
switch override.URLTemplate {
207+
switch override.BaseURL {
207208
case "":
208209
case "default":
209-
spec.URLTemplate = ""
210+
spec.BaseURL = ""
210211
default:
211-
spec.URLTemplate = override.URLTemplate
212+
spec.BaseURL = override.BaseURL
212213
}
213-
if spec.URLTemplate != "" &&
214-
!strings.HasPrefix(strings.ToLower(spec.URLTemplate), "https://") {
215-
return trace.Errorf("Teleport download URL must use TLS (https://)")
214+
if spec.BaseURL != "" &&
215+
!strings.HasPrefix(strings.ToLower(spec.BaseURL), "https://") {
216+
return trace.Errorf("Teleport download base URL %s must use TLS (https://)", spec.BaseURL)
216217
}
217218
if override.Enabled {
218219
spec.Enabled = true
@@ -239,89 +240,3 @@ type FindResp struct {
239240
// Jitter duration before an automated install
240241
Jitter time.Duration `yaml:"jitter"`
241242
}
242-
243-
// InstallFlags sets flags for the Teleport installation
244-
type InstallFlags int
245-
246-
const (
247-
// FlagEnterprise installs enterprise Teleport
248-
FlagEnterprise InstallFlags = 1 << iota
249-
// FlagFIPS installs FIPS Teleport
250-
FlagFIPS
251-
)
252-
253-
// NewInstallFlagsFromStrings returns InstallFlags given a slice of human-readable strings.
254-
func NewInstallFlagsFromStrings(s []string) InstallFlags {
255-
var out InstallFlags
256-
for _, f := range s {
257-
for _, flag := range []InstallFlags{
258-
FlagEnterprise,
259-
FlagFIPS,
260-
} {
261-
if f == flag.String() {
262-
out |= flag
263-
}
264-
}
265-
}
266-
return out
267-
}
268-
269-
// Strings converts InstallFlags to a slice of human-readable strings.
270-
func (i InstallFlags) Strings() []string {
271-
var out []string
272-
for _, flag := range []InstallFlags{
273-
FlagEnterprise,
274-
FlagFIPS,
275-
} {
276-
if i&flag != 0 {
277-
out = append(out, flag.String())
278-
}
279-
}
280-
return out
281-
}
282-
283-
// String returns the string representation of a single InstallFlag flag, or "Unknown".
284-
func (i InstallFlags) String() string {
285-
switch i {
286-
case 0:
287-
return ""
288-
case FlagEnterprise:
289-
return "Enterprise"
290-
case FlagFIPS:
291-
return "FIPS"
292-
}
293-
return "Unknown"
294-
}
295-
296-
// DirFlag returns the directory path representation of a single InstallFlag flag, or "unknown".
297-
func (i InstallFlags) DirFlag() string {
298-
switch i {
299-
case 0:
300-
return ""
301-
case FlagEnterprise:
302-
return "ent"
303-
case FlagFIPS:
304-
return "fips"
305-
}
306-
return "unknown"
307-
}
308-
309-
func (i InstallFlags) MarshalYAML() (any, error) {
310-
return i.Strings(), nil
311-
}
312-
313-
func (i InstallFlags) MarshalJSON() ([]byte, error) {
314-
return json.Marshal(i.Strings())
315-
}
316-
317-
func (i *InstallFlags) UnmarshalYAML(n *yaml.Node) error {
318-
var s []string
319-
if err := n.Decode(&s); err != nil {
320-
return trace.Wrap(err)
321-
}
322-
if i == nil {
323-
return trace.BadParameter("nil install flags while parsing YAML")
324-
}
325-
*i = NewInstallFlagsFromStrings(s)
326-
return nil
327-
}

lib/autoupdate/agent/config_test.go

Lines changed: 4 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import (
2222
"testing"
2323

2424
"github.com/stretchr/testify/require"
25-
"gopkg.in/yaml.v3"
25+
26+
"github.com/gravitational/teleport/lib/autoupdate"
2627
)
2728

2829
func TestNewRevisionFromDir(t *testing.T) {
@@ -46,15 +47,15 @@ func TestNewRevisionFromDir(t *testing.T) {
4647
dir: "1.2.3_ent_fips",
4748
rev: Revision{
4849
Version: "1.2.3",
49-
Flags: FlagEnterprise | FlagFIPS,
50+
Flags: autoupdate.FlagEnterprise | autoupdate.FlagFIPS,
5051
},
5152
},
5253
{
5354
name: "ent",
5455
dir: "1.2.3_ent",
5556
rev: Revision{
5657
Version: "1.2.3",
57-
Flags: FlagEnterprise,
58+
Flags: autoupdate.FlagEnterprise,
5859
},
5960
},
6061
{
@@ -124,72 +125,3 @@ func TestNewRevisionFromDir(t *testing.T) {
124125
})
125126
}
126127
}
127-
128-
func TestInstallFlagsYAML(t *testing.T) {
129-
t.Parallel()
130-
131-
for _, tt := range []struct {
132-
name string
133-
yaml string
134-
flags InstallFlags
135-
skipYAML bool
136-
}{
137-
{
138-
name: "both",
139-
yaml: `["Enterprise", "FIPS"]`,
140-
flags: FlagEnterprise | FlagFIPS,
141-
},
142-
{
143-
name: "order",
144-
yaml: `["FIPS", "Enterprise"]`,
145-
flags: FlagEnterprise | FlagFIPS,
146-
skipYAML: true,
147-
},
148-
{
149-
name: "extra",
150-
yaml: `["FIPS", "Enterprise", "bad"]`,
151-
flags: FlagEnterprise | FlagFIPS,
152-
skipYAML: true,
153-
},
154-
{
155-
name: "enterprise",
156-
yaml: `["Enterprise"]`,
157-
flags: FlagEnterprise,
158-
},
159-
{
160-
name: "fips",
161-
yaml: `["FIPS"]`,
162-
flags: FlagFIPS,
163-
},
164-
{
165-
name: "empty",
166-
yaml: `[]`,
167-
},
168-
{
169-
name: "nil",
170-
skipYAML: true,
171-
},
172-
} {
173-
t.Run(tt.name, func(t *testing.T) {
174-
var flags InstallFlags
175-
err := yaml.Unmarshal([]byte(tt.yaml), &flags)
176-
require.NoError(t, err)
177-
require.Equal(t, tt.flags, flags)
178-
179-
// verify test YAML
180-
var v any
181-
err = yaml.Unmarshal([]byte(tt.yaml), &v)
182-
require.NoError(t, err)
183-
res, err := yaml.Marshal(v)
184-
require.NoError(t, err)
185-
186-
// compare verified YAML to flag output
187-
out, err := yaml.Marshal(flags)
188-
require.NoError(t, err)
189-
190-
if !tt.skipYAML {
191-
require.Equal(t, string(res), string(out))
192-
}
193-
})
194-
}
195-
}

lib/autoupdate/agent/installer.go

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,14 @@ import (
3131
"os"
3232
"path"
3333
"path/filepath"
34-
"runtime"
3534
"syscall"
36-
"text/template"
3735
"time"
3836

3937
"github.com/google/renameio/v2"
4038
"github.com/gravitational/trace"
4139

4240
"github.com/gravitational/teleport"
41+
"github.com/gravitational/teleport/lib/autoupdate"
4342
"github.com/gravitational/teleport/lib/utils"
4443
)
4544

@@ -89,6 +88,8 @@ type LocalInstaller struct {
8988
// ValidateBinary returns true if a file is a linkable binary, or
9089
// false if a file should not be linked.
9190
ValidateBinary func(ctx context.Context, path string) (bool, error)
91+
// Template is download URI Template of Teleport packages.
92+
Template string
9293
}
9394

9495
// Remove a Teleport version directory from InstallDir.
@@ -127,15 +128,15 @@ func (li *LocalInstaller) Remove(ctx context.Context, rev Revision) error {
127128
// Install a Teleport version directory in InstallDir.
128129
// This function is idempotent.
129130
// See Installer interface for additional specs.
130-
func (li *LocalInstaller) Install(ctx context.Context, rev Revision, template string) (err error) {
131+
func (li *LocalInstaller) Install(ctx context.Context, rev Revision, baseURL string) (err error) {
131132
versionDir, err := li.revisionDir(rev)
132133
if err != nil {
133134
return trace.Wrap(err)
134135
}
135136
sumPath := filepath.Join(versionDir, checksumType)
136137

137-
// generate download URI from template
138-
uri, err := makeURL(template, rev)
138+
// generate download URI from Template
139+
uri, err := autoupdate.MakeURL(li.Template, baseURL, autoupdate.DefaultPackage, rev.Version, rev.Flags)
139140
if err != nil {
140141
return trace.Wrap(err)
141142
}
@@ -229,30 +230,6 @@ func (li *LocalInstaller) Install(ctx context.Context, rev Revision, template st
229230
return nil
230231
}
231232

232-
// makeURL to download the Teleport tgz.
233-
func makeURL(uriTmpl string, rev Revision) (string, error) {
234-
tmpl, err := template.New("uri").Parse(uriTmpl)
235-
if err != nil {
236-
return "", trace.Wrap(err)
237-
}
238-
var uriBuf bytes.Buffer
239-
params := struct {
240-
OS, Version, Arch string
241-
FIPS, Enterprise bool
242-
}{
243-
OS: runtime.GOOS,
244-
Version: rev.Version,
245-
Arch: runtime.GOARCH,
246-
FIPS: rev.Flags&FlagFIPS != 0,
247-
Enterprise: rev.Flags&(FlagEnterprise|FlagFIPS) != 0,
248-
}
249-
err = tmpl.Execute(&uriBuf, params)
250-
if err != nil {
251-
return "", trace.Wrap(err)
252-
}
253-
return uriBuf.String(), nil
254-
}
255-
256233
// readChecksum from the version directory.
257234
func readChecksum(path string) ([]byte, error) {
258235
f, err := os.Open(path)
@@ -354,7 +331,7 @@ func (li *LocalInstaller) download(ctx context.Context, w io.Writer, max int64,
354331
return shaReader.Sum(nil), nil
355332
}
356333

357-
func (li *LocalInstaller) extract(ctx context.Context, dstDir string, src io.Reader, max int64, flags InstallFlags) error {
334+
func (li *LocalInstaller) extract(ctx context.Context, dstDir string, src io.Reader, max int64, flags autoupdate.InstallFlags) error {
358335
if err := os.MkdirAll(dstDir, systemDirMode); err != nil {
359336
return trace.Wrap(err)
360337
}
@@ -372,7 +349,7 @@ func (li *LocalInstaller) extract(ctx context.Context, dstDir string, src io.Rea
372349
}
373350
li.Log.InfoContext(ctx, "Extracting Teleport tarball.", "path", dstDir, "size", max)
374351

375-
err = utils.Extract(zr, dstDir, tgzExtractPaths(flags&(FlagEnterprise|FlagFIPS) != 0)...)
352+
err = utils.Extract(zr, dstDir, tgzExtractPaths(flags&(autoupdate.FlagEnterprise|autoupdate.FlagFIPS) != 0)...)
376353
if err != nil {
377354
return trace.Wrap(err)
378355
}

0 commit comments

Comments
 (0)