Skip to content

Commit 71ecc83

Browse files
authored
Merge pull request #3727 from ActiveState/CP-1054-follow-up
Update config to override correct URL
2 parents 36d4396 + dd35ebf commit 71ecc83

8 files changed

Lines changed: 133 additions & 25 deletions

File tree

cmd/state-remote-installer/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func execute(out output.Outputer, prompt prompt.Prompter, cfg *config.Instance,
208208
version = fmt.Sprintf("%s (%s)", version, channel)
209209
}
210210

211-
update := updater.NewUpdateInstaller(an, availableUpdate)
211+
update := updater.NewUpdateInstaller(cfg, an, availableUpdate)
212212
out.Fprint(os.Stdout, locale.Tl("remote_install_downloading", "• Downloading State Tool version [NOTICE]{{.V0}}[/RESET]... ", version))
213213
tmpDir, err := update.DownloadAndUnpack()
214214
if err != nil {

cmd/state/autoupdate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func autoUpdate(svc *model.SvcModel, args []string, childCmd *captain.Command, c
5353
}
5454

5555
avUpdate := updater.NewAvailableUpdate(upd.Channel, upd.Version, upd.Platform, upd.Path, upd.Sha256, "")
56-
up := updater.NewUpdateInstaller(an, avUpdate)
56+
up := updater.NewUpdateInstaller(cfg, an, avUpdate)
5757
if !up.ShouldInstall() {
5858
logging.Debug("Update is not needed")
5959
return false, nil

internal/constants/constants.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ const OverwriteDefaultSystemPathEnvVarName = "ACTIVESTATE_TEST_SYSTEM_PATH"
133133
// TestAutoUpdateEnvVarName is used to test auto updates, when set to true will always attempt to auto update
134134
const TestAutoUpdateEnvVarName = "ACTIVESTATE_TEST_AUTO_UPDATE"
135135

136+
// TestUpdateInfoURLEnvVarName is used to test update info urls, when set to a url will override the default update info url
137+
const TestUpdateInfoURLEnvVarName = "ACTIVESTATE_TEST_UPDATE_INFO_URL"
138+
139+
// TestUpdateURLEnvVarName is used to test update urls, when set to a url will override the default update url
140+
const TestUpdateURLEnvVarName = "ACTIVESTATE_TEST_UPDATE_URL"
141+
136142
// ForceUpdateEnvVarName is used to force state tool to update, regardless of whether the update is equal to the current version
137143
const ForceUpdateEnvVarName = "ACTIVESTATE_FORCE_UPDATE"
138144

@@ -418,6 +424,9 @@ const AnalyticsPixelOverrideConfig = "report.analytics.endpoint"
418424
// UpdateEndpointConfig is the config key used to determine the update endpoint to use
419425
const UpdateEndpointConfig = "update.endpoint"
420426

427+
// UpdateInfoEndpointConfig is the config key used to determine the update info endpoint to use
428+
const UpdateInfoEndpointConfig = "update.info.endpoint"
429+
421430
// NotificationsURLConfig is the config key used to determine the notifications url to use
422431
const NotificationsURLConfig = "notifications.endpoint"
423432

internal/runners/update/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func (u *Update) Run(params *Params) error {
6565
))
6666
}
6767

68-
update := updater.NewUpdateInstaller(u.an, upd)
68+
update := updater.NewUpdateInstaller(u.cfg, u.an, upd)
6969
if !update.ShouldInstall() {
7070
logging.Debug("No update found")
7171
u.out.Print(output.Prepare(

internal/updater/checker.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var (
3535
)
3636

3737
func init() {
38-
configMediator.RegisterOption(constants.UpdateEndpointConfig, configMediator.String, "")
38+
configMediator.RegisterOption(constants.UpdateInfoEndpointConfig, configMediator.String, "")
3939
}
4040

4141
type Checker struct {
@@ -86,8 +86,8 @@ func (u *Checker) infoURL(tag, desiredVersion, branchName, platform, arch string
8686
var (
8787
infoURL string
8888

89-
envUrl = os.Getenv("_TEST_UPDATE_INFO_URL")
90-
cfgUrl = u.cfg.GetString(constants.UpdateEndpointConfig)
89+
envUrl = os.Getenv(constants.TestUpdateInfoURLEnvVarName)
90+
cfgUrl = u.cfg.GetString(constants.UpdateInfoEndpointConfig)
9191
)
9292
switch {
9393
case envUrl != "":

internal/updater/updater.go

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/ActiveState/cli/internal/installation/storage"
2424
"github.com/ActiveState/cli/internal/locale"
2525
"github.com/ActiveState/cli/internal/logging"
26+
configMediator "github.com/ActiveState/cli/internal/mediators/config"
2627
"github.com/ActiveState/cli/internal/multilog"
2728
"github.com/ActiveState/cli/internal/osutils"
2829
"github.com/ActiveState/cli/internal/rtutils"
@@ -34,6 +35,10 @@ const (
3435
InstallerName = "state-installer" + osutils.ExeExtension
3536
)
3637

38+
func init() {
39+
configMediator.RegisterOption(constants.UpdateEndpointConfig, configMediator.String, "")
40+
}
41+
3742
type ErrorInProgress struct{ *locale.LocalizedError }
3843

3944
var errPrivilegeMistmatch = errs.New("Privilege mismatch")
@@ -101,22 +106,40 @@ type UpdateInstaller struct {
101106

102107
// NewUpdateInstallerByOrigin returns an instance of Update. Allowing origin to
103108
// be set is useful for testing.
104-
func NewUpdateInstallerByOrigin(an analytics.Dispatcher, origin *Origin, avUpdate *AvailableUpdate) *UpdateInstaller {
105-
apiUpdateURL := constants.APIUpdateURL
106-
if url, ok := os.LookupEnv("_TEST_UPDATE_URL"); ok {
107-
apiUpdateURL = url
108-
}
109-
110-
return &UpdateInstaller{
109+
func NewUpdateInstallerByOrigin(cfg Configurable, an analytics.Dispatcher, origin *Origin, avUpdate *AvailableUpdate) *UpdateInstaller {
110+
updater := &UpdateInstaller{
111111
AvailableUpdate: avUpdate,
112112
Origin: origin,
113-
url: apiUpdateURL + "/" + avUpdate.Path,
113+
url: getAPIUpdateURL(cfg, avUpdate.Path),
114114
an: an,
115115
}
116+
117+
configMediator.AddListener(constants.UpdateEndpointConfig, func() {
118+
updater.url = getAPIUpdateURL(cfg, avUpdate.Path)
119+
})
120+
121+
return updater
122+
}
123+
124+
func NewUpdateInstaller(cfg Configurable, an analytics.Dispatcher, avUpdate *AvailableUpdate) *UpdateInstaller {
125+
return NewUpdateInstallerByOrigin(cfg, an, NewOriginDefault(), avUpdate)
116126
}
117127

118-
func NewUpdateInstaller(an analytics.Dispatcher, avUpdate *AvailableUpdate) *UpdateInstaller {
119-
return NewUpdateInstallerByOrigin(an, NewOriginDefault(), avUpdate)
128+
func getAPIUpdateURL(cfg Configurable, path string) string {
129+
var apiUpdateURL string
130+
131+
envUrl := os.Getenv(constants.TestUpdateURLEnvVarName)
132+
cfgUrl := cfg.GetString(constants.UpdateEndpointConfig)
133+
switch {
134+
case envUrl != "":
135+
apiUpdateURL = envUrl
136+
case cfgUrl != "":
137+
apiUpdateURL = cfgUrl
138+
default:
139+
apiUpdateURL = constants.APIUpdateURL
140+
}
141+
142+
return apiUpdateURL + "/" + path
120143
}
121144

122145
func (u *UpdateInstaller) ShouldInstall() bool {

internal/updater/updater_test.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ import (
66
"github.com/stretchr/testify/assert"
77
)
88

9+
type mockConfig struct{}
10+
11+
func (m *mockConfig) GetString(key string) string {
12+
return ""
13+
}
14+
15+
func (m *mockConfig) Set(key string, value interface{}) error {
16+
return nil
17+
}
18+
919
func newAvailableUpdate(channel, version string) *AvailableUpdate {
1020
return NewAvailableUpdate(channel, version, "platform", "path/to/zipfile.zip", "123456", "")
1121
}
@@ -45,7 +55,7 @@ func TestUpdateNotNeeded(t *testing.T) {
4555

4656
for _, tt := range tests {
4757
t.Run(tt.Name, func(t *testing.T) {
48-
upd := NewUpdateInstallerByOrigin(nil, tt.Origin, tt.AvailableUpdate)
58+
upd := NewUpdateInstallerByOrigin(&mockConfig{}, nil, tt.Origin, tt.AvailableUpdate)
4959
assert.Equal(t, tt.IsUseful, upd.ShouldInstall())
5060
})
5161
}

test/integration/update_int_test.go

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -275,14 +275,14 @@ func (suite *UpdateIntegrationTestSuite) TestUpdateTags() {
275275
}
276276
}
277277

278-
func (suite *UpdateIntegrationTestSuite) TestUpdateHost_SetBeforeInvocation() {
278+
func (suite *UpdateIntegrationTestSuite) TestUpdateInfoHost_SetBeforeInvocation() {
279279
suite.OnlyRunForTags(tagsuite.Update)
280280

281281
ts := e2e.New(suite.T(), false)
282282
defer ts.Close()
283283

284-
ts.SetConfig(constants.UpdateEndpointConfig, "https://test.example.com/update")
285-
suite.Assert().Equal(ts.GetConfig(constants.UpdateEndpointConfig), "https://test.example.com/update")
284+
ts.SetConfig(constants.UpdateInfoEndpointConfig, "https://test.example.com/update")
285+
suite.Assert().Equal(ts.GetConfig(constants.UpdateInfoEndpointConfig), "https://test.example.com/update")
286286

287287
cp := ts.SpawnWithOpts(
288288
e2e.OptArgs("--version"),
@@ -303,6 +303,62 @@ func (suite *UpdateIntegrationTestSuite) TestUpdateHost_SetBeforeInvocation() {
303303
suite.Assert().Greater(correctHostCount, 0, "Log file should contain the configured API host 'test.example.com'")
304304
suite.Assert().Equal(incorrectHostCount, 0, "Log file should not contain the default API host 'platform.activestate.com'")
305305

306+
// Clean up - remove the config setting
307+
cp = ts.Spawn("config", "set", constants.UpdateInfoEndpointConfig, "")
308+
cp.Expect("Successfully")
309+
cp.ExpectExitCode(0)
310+
}
311+
312+
func (suite *UpdateIntegrationTestSuite) TestUpdateInfoHost() {
313+
suite.OnlyRunForTags(tagsuite.Update)
314+
315+
ts := e2e.New(suite.T(), false)
316+
defer ts.Close()
317+
318+
cp := ts.Spawn("config", "set", constants.UpdateInfoEndpointConfig, "https://example.com/update-info")
319+
cp.Expect("Successfully set config key")
320+
cp.ExpectExitCode(0)
321+
322+
cp = ts.SpawnWithOpts(
323+
e2e.OptArgs("update", "-v"),
324+
e2e.OptAppendEnv(suite.env(false, false)...),
325+
)
326+
cp.ExpectExitCode(0)
327+
328+
output := cp.Snapshot()
329+
suite.Assert().Contains(output, "Getting update info: https://example.com/update-info/")
330+
}
331+
332+
func (suite *UpdateIntegrationTestSuite) TestUpdateHost_SetBeforeInvocation() {
333+
suite.OnlyRunForTags(tagsuite.Update)
334+
335+
ts := e2e.New(suite.T(), false)
336+
defer ts.Close()
337+
338+
ts.SetConfig(constants.UpdateInfoEndpointConfig, "https://test.example.com/update")
339+
suite.Assert().Equal(ts.GetConfig(constants.UpdateInfoEndpointConfig), "https://test.example.com/update")
340+
341+
cp := ts.SpawnWithOpts(
342+
e2e.OptArgs("update", "-v"),
343+
e2e.OptAppendEnv(suite.env(false, false)...),
344+
)
345+
cp.ExpectExitCode(11) // Expect failure due to DNS resolution of fake host
346+
ts.IgnoreLogErrors()
347+
348+
correctHostCount := 0
349+
incorrectHostCount := 0
350+
for _, path := range ts.LogFiles() {
351+
contents := string(fileutils.ReadFileUnsafe(path))
352+
if strings.Contains(contents, "https://test.example.com/update") {
353+
correctHostCount++
354+
}
355+
if strings.Contains(contents, "https://state-tool.activestate.com/update") {
356+
incorrectHostCount++
357+
}
358+
}
359+
suite.Assert().Greater(correctHostCount, 0, "Log file should contain the configured update endpoint 'test.example.com'")
360+
suite.Assert().Equal(incorrectHostCount, 0, "Log file should not contain the default update endpoint 'state-tool.activestate.com'")
361+
306362
// Clean up - remove the config setting
307363
cp = ts.Spawn("config", "set", constants.UpdateEndpointConfig, "")
308364
cp.Expect("Successfully")
@@ -315,19 +371,29 @@ func (suite *UpdateIntegrationTestSuite) TestUpdateHost() {
315371
ts := e2e.New(suite.T(), false)
316372
defer ts.Close()
317373

318-
cp := ts.Spawn("config", "set", constants.UpdateEndpointConfig, "https://example.com/update")
374+
cp := ts.Spawn("config", "set", constants.UpdateEndpointConfig, "https://test.example.com/update")
319375
cp.Expect("Successfully set config key")
320376
cp.ExpectExitCode(0)
321377

322378
cp = ts.SpawnWithOpts(
323-
e2e.OptArgs("update"),
379+
e2e.OptArgs("update", "-v"),
324380
e2e.OptAppendEnv(suite.env(false, false)...),
325-
e2e.OptAppendEnv("VERBOSE=true"),
326381
)
327382
cp.ExpectExitCode(0)
328383

329-
output := cp.Snapshot()
330-
suite.Assert().Contains(output, "Getting update info: https://example.com/update/")
384+
correctHostCount := 0
385+
incorrectHostCount := 0
386+
for _, path := range ts.LogFiles() {
387+
contents := string(fileutils.ReadFileUnsafe(path))
388+
if strings.Contains(contents, "https://test.example.com/update") {
389+
correctHostCount++
390+
}
391+
if strings.Contains(contents, "https://state-tool.activestate.com/update") {
392+
incorrectHostCount++
393+
}
394+
}
395+
suite.Assert().Greater(correctHostCount, 0, "Log file should contain the configured update endpoint 'example.com'")
396+
suite.Assert().Equal(incorrectHostCount, 0, "Log file should not contain the default update endpoint 'state-tool.activestate.com'")
331397
}
332398

333399
func TestUpdateIntegrationTestSuite(t *testing.T) {

0 commit comments

Comments
 (0)