Skip to content

Commit

Permalink
Client AutoUpdate proto structure changes (#47532)
Browse files Browse the repository at this point in the history
* Update client autoupdate proto structure

* Replace with reserved

* Fix unit tests

* Add more info in proto

* Rename proto to be aligned RFD namings

* Replace enum type for ToolsMode to string
  • Loading branch information
vapopov committed Oct 17, 2024
1 parent 076cd02 commit 6ddfd56
Show file tree
Hide file tree
Showing 13 changed files with 365 additions and 111 deletions.
4 changes: 2 additions & 2 deletions api/client/webclient/webclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,8 @@ type ProxySettings struct {
type AutoUpdateSettings struct {
// ToolsVersion defines the version of {tsh, tctl} for client auto update.
ToolsVersion string `json:"tools_version"`
// ToolsAutoUpdate enables client auto update feature.
ToolsAutoUpdate bool `json:"tools_auto_update"`
// ToolsMode defines mode client auto update feature `enabled|disabled`.
ToolsMode string `json:"tools_mode"`
}

// KubeProxySettings is kubernetes proxy settings
Expand Down
258 changes: 199 additions & 59 deletions api/gen/proto/go/teleport/autoupdate/v1/autoupdate.pb.go

Large diffs are not rendered by default.

23 changes: 19 additions & 4 deletions api/proto/teleport/autoupdate/v1/autoupdate.proto
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,15 @@ message AutoUpdateConfig {

// AutoUpdateConfigSpec encodes the parameters of the autoupdate config object.
message AutoUpdateConfigSpec {
// ToolsAutoupdate encodes the feature flag to enable/disable tools autoupdates.
bool tools_autoupdate = 1;
reserved 1;
reserved "tools_autoupdate"; // ToolsAutoupdate is replaced by tools.mode.
AutoUpdateConfigSpecTools tools = 2;
}

// AutoUpdateConfigSpecTools encodes the parameters for client tools auto updates.
message AutoUpdateConfigSpecTools {
// Mode defines state of the client tools auto update.
string mode = 1;
}

// AutoUpdateVersion is a resource singleton with version required for
Expand All @@ -50,6 +57,14 @@ message AutoUpdateVersion {

// AutoUpdateVersionSpec encodes the parameters of the autoupdate versions.
message AutoUpdateVersionSpec {
// ToolsVersion is the semantic version required for tools autoupdates.
string tools_version = 1;
reserved 1;
reserved "tools_version"; // ToolsVersion is replaced by tools.target_version.
AutoUpdateVersionSpecTools tools = 2;
}

// AutoUpdateVersionSpecTools encodes the parameters for client tools auto updates.
message AutoUpdateVersionSpecTools {
// TargetVersion specifies the semantic version required for tools to establish a connection with the cluster.
// Client tools after connection to the cluster going to be updated to this version automatically.
string target_version = 1;
}
12 changes: 12 additions & 0 deletions api/types/autoupdate/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ import (
"github.com/gravitational/teleport/api/types"
)

const (
// ToolsUpdateModeEnabled enables client tools automatic updates.
ToolsUpdateModeEnabled = "enabled"
// ToolsUpdateModeDisabled disables client tools automatic updates.
ToolsUpdateModeDisabled = "disabled"
)

// NewAutoUpdateConfig creates a new auto update configuration resource.
func NewAutoUpdateConfig(spec *autoupdate.AutoUpdateConfigSpec) (*autoupdate.AutoUpdateConfig, error) {
config := &autoupdate.AutoUpdateConfig{
Expand Down Expand Up @@ -58,6 +65,11 @@ func ValidateAutoUpdateConfig(c *autoupdate.AutoUpdateConfig) error {
if c.Spec == nil {
return trace.BadParameter("Spec is nil")
}
if c.Spec.Tools != nil {
if c.Spec.Tools.Mode != ToolsUpdateModeDisabled && c.Spec.Tools.Mode != ToolsUpdateModeEnabled {
return trace.BadParameter("ToolsMode is not valid")
}
}

return nil
}
27 changes: 23 additions & 4 deletions api/types/autoupdate/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ func TestNewAutoUpdateConfig(t *testing.T) {
{
name: "success tools autoupdate disabled",
spec: &autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: false,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: ToolsUpdateModeDisabled,
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.NoError(t, err)
Expand All @@ -53,14 +55,18 @@ func TestNewAutoUpdateConfig(t *testing.T) {
Name: types.MetaNameAutoUpdateConfig,
},
Spec: &autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: false,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: ToolsUpdateModeDisabled,
},
},
},
},
{
name: "success tools autoupdate enabled",
spec: &autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: true,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: ToolsUpdateModeEnabled,
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.NoError(t, err)
Expand All @@ -72,7 +78,9 @@ func TestNewAutoUpdateConfig(t *testing.T) {
Name: types.MetaNameAutoUpdateConfig,
},
Spec: &autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: true,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: ToolsUpdateModeEnabled,
},
},
},
},
Expand All @@ -83,6 +91,17 @@ func TestNewAutoUpdateConfig(t *testing.T) {
require.ErrorContains(t, err, "Spec is nil")
},
},
{
name: "invalid tools mode",
spec: &autoupdate.AutoUpdateConfigSpec{
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: "invalid-mode",
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.ErrorContains(t, err, "ToolsMode is not valid")
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
12 changes: 7 additions & 5 deletions api/types/autoupdate/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ func ValidateAutoUpdateVersion(v *autoupdate.AutoUpdateVersion) error {
return trace.BadParameter("Spec is nil")
}

if v.Spec.ToolsVersion == "" {
return trace.BadParameter("ToolsVersion is unset")
}
if _, err := semver.NewVersion(v.Spec.ToolsVersion); err != nil {
return trace.BadParameter("ToolsVersion is not a valid semantic version")
if v.Spec.Tools != nil {
if v.Spec.Tools.TargetVersion == "" {
return trace.BadParameter("TargetVersion is unset")
}
if _, err := semver.NewVersion(v.Spec.Tools.TargetVersion); err != nil {
return trace.BadParameter("TargetVersion is not a valid semantic version")
}
}

return nil
Expand Down
20 changes: 14 additions & 6 deletions api/types/autoupdate/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ func TestNewAutoUpdateVersion(t *testing.T) {
{
name: "success tools autoupdate version",
spec: &autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "1.2.3-dev",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "1.2.3-dev",
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.NoError(t, err)
Expand All @@ -53,26 +55,32 @@ func TestNewAutoUpdateVersion(t *testing.T) {
Name: types.MetaNameAutoUpdateVersion,
},
Spec: &autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "1.2.3-dev",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "1.2.3-dev",
},
},
},
},
{
name: "invalid empty tools version",
spec: &autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "",
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.ErrorContains(t, err, "ToolsVersion is unset")
require.ErrorContains(t, err, "TargetVersion is unset")
},
},
{
name: "invalid semantic tools version",
spec: &autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "17-0-0",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "17-0-0",
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.ErrorContains(t, err, "ToolsVersion is not a valid semantic version")
require.ErrorContains(t, err, "TargetVersion is not a valid semantic version")
},
},
{
Expand Down
8 changes: 6 additions & 2 deletions lib/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3563,7 +3563,9 @@ func newAutoUpdateConfig(t *testing.T) *autoupdate.AutoUpdateConfig {
t.Helper()

r, err := update.NewAutoUpdateConfig(&autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: true,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: update.ToolsUpdateModeEnabled,
},
})
require.NoError(t, err)
return r
Expand All @@ -3573,7 +3575,9 @@ func newAutoUpdateVersion(t *testing.T) *autoupdate.AutoUpdateVersion {
t.Helper()

r, err := update.NewAutoUpdateVersion(&autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "1.2.3",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "1.2.3",
},
})
require.NoError(t, err)
return r
Expand Down
48 changes: 38 additions & 10 deletions lib/services/local/autoupdate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ func TestAutoUpdateServiceConfigCRUD(t *testing.T) {
Kind: types.KindAutoUpdateConfig,
Version: types.V1,
Metadata: &headerv1.Metadata{Name: types.MetaNameAutoUpdateConfig},
Spec: &autoupdatev1pb.AutoUpdateConfigSpec{ToolsAutoupdate: true},
Spec: &autoupdatev1pb.AutoUpdateConfigSpec{
Tools: &autoupdatev1pb.AutoUpdateConfigSpecTools{
Mode: autoupdate.ToolsUpdateModeEnabled,
},
},
}

created, err := service.CreateAutoUpdateConfig(ctx, config)
Expand All @@ -71,10 +75,12 @@ func TestAutoUpdateServiceConfigCRUD(t *testing.T) {
require.Empty(t, diff)
require.Equal(t, created.GetMetadata().GetRevision(), got.GetMetadata().GetRevision())

config.Spec.ToolsAutoupdate = false
config.Spec.Tools = &autoupdatev1pb.AutoUpdateConfigSpecTools{
Mode: autoupdate.ToolsUpdateModeDisabled,
}
updated, err := service.UpdateAutoUpdateConfig(ctx, config)
require.NoError(t, err)
require.NotEqual(t, got.GetSpec().GetToolsAutoupdate(), updated.GetSpec().GetToolsAutoupdate())
require.NotEqual(t, got.GetSpec().GetTools(), updated.GetSpec().GetTools())

_, err = service.UpsertAutoUpdateConfig(ctx, config)
require.NoError(t, err)
Expand Down Expand Up @@ -106,7 +112,11 @@ func TestAutoUpdateServiceVersionCRUD(t *testing.T) {
Kind: types.KindAutoUpdateVersion,
Version: types.V1,
Metadata: &headerv1.Metadata{Name: types.MetaNameAutoUpdateVersion},
Spec: &autoupdatev1pb.AutoUpdateVersionSpec{ToolsVersion: "1.2.3"},
Spec: &autoupdatev1pb.AutoUpdateVersionSpec{
Tools: &autoupdatev1pb.AutoUpdateVersionSpecTools{
TargetVersion: "1.2.3",
},
},
}

created, err := service.CreateAutoUpdateVersion(ctx, version)
Expand All @@ -126,10 +136,12 @@ func TestAutoUpdateServiceVersionCRUD(t *testing.T) {
require.Empty(t, diff)
require.Equal(t, created.GetMetadata().GetRevision(), got.GetMetadata().GetRevision())

version.Spec.ToolsVersion = "3.2.1"
version.Spec.Tools = &autoupdatev1pb.AutoUpdateVersionSpecTools{
TargetVersion: "3.2.1",
}
updated, err := service.UpdateAutoUpdateVersion(ctx, version)
require.NoError(t, err)
require.NotEqual(t, got.GetSpec().GetToolsVersion(), updated.GetSpec().GetToolsVersion())
require.NotEqual(t, got.GetSpec().GetTools().GetTargetVersion(), updated.GetSpec().GetTools().GetTargetVersion())

_, err = service.UpsertAutoUpdateVersion(ctx, version)
require.NoError(t, err)
Expand Down Expand Up @@ -161,7 +173,11 @@ func TestAutoUpdateServiceInvalidNameCreate(t *testing.T) {
Kind: types.KindAutoUpdateConfig,
Version: types.V1,
Metadata: &headerv1.Metadata{Name: "invalid-auto-update-config-name"},
Spec: &autoupdatev1pb.AutoUpdateConfigSpec{ToolsAutoupdate: true},
Spec: &autoupdatev1pb.AutoUpdateConfigSpec{
Tools: &autoupdatev1pb.AutoUpdateConfigSpecTools{
Mode: autoupdate.ToolsUpdateModeEnabled,
},
},
}

createdConfig, err := service.CreateAutoUpdateConfig(ctx, config)
Expand All @@ -172,7 +188,11 @@ func TestAutoUpdateServiceInvalidNameCreate(t *testing.T) {
Kind: types.KindAutoUpdateVersion,
Version: types.V1,
Metadata: &headerv1.Metadata{Name: "invalid-auto-update-version-name"},
Spec: &autoupdatev1pb.AutoUpdateVersionSpec{ToolsVersion: "1.2.3"},
Spec: &autoupdatev1pb.AutoUpdateVersionSpec{
Tools: &autoupdatev1pb.AutoUpdateVersionSpecTools{
TargetVersion: "1.2.3",
},
},
}

createdVersion, err := service.CreateAutoUpdateVersion(ctx, version)
Expand All @@ -194,7 +214,11 @@ func TestAutoUpdateServiceInvalidNameUpdate(t *testing.T) {
ctx := context.Background()

// Validate the config update restriction.
config, err := autoupdate.NewAutoUpdateConfig(&autoupdatev1pb.AutoUpdateConfigSpec{ToolsAutoupdate: true})
config, err := autoupdate.NewAutoUpdateConfig(&autoupdatev1pb.AutoUpdateConfigSpec{
Tools: &autoupdatev1pb.AutoUpdateConfigSpecTools{
Mode: autoupdate.ToolsUpdateModeEnabled,
},
})
require.NoError(t, err)

createdConfig, err := service.UpsertAutoUpdateConfig(ctx, config)
Expand All @@ -207,7 +231,11 @@ func TestAutoUpdateServiceInvalidNameUpdate(t *testing.T) {
require.Nil(t, createdConfig)

// Validate the version update restriction.
version, err := autoupdate.NewAutoUpdateVersion(&autoupdatev1pb.AutoUpdateVersionSpec{ToolsVersion: "1.2.3"})
version, err := autoupdate.NewAutoUpdateVersion(&autoupdatev1pb.AutoUpdateVersionSpec{
Tools: &autoupdatev1pb.AutoUpdateVersionSpecTools{
TargetVersion: "1.2.3",
},
})
require.NoError(t, err)

createdVersion, err := service.UpsertAutoUpdateVersion(ctx, version)
Expand Down
4 changes: 2 additions & 2 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1427,15 +1427,15 @@ func (h *Handler) find(w http.ResponseWriter, r *http.Request, p httprouter.Para
if err != nil && !trace.IsNotFound(err) && !trace.IsNotImplemented(err) {
h.log.WithError(err).Error("failed to receive AutoUpdateConfig")
} else if err == nil {
response.AutoUpdate.ToolsAutoUpdate = autoUpdateConfig.GetSpec().GetToolsAutoupdate()
response.AutoUpdate.ToolsMode = autoUpdateConfig.GetSpec().GetTools().GetMode()
}

autoUpdateVersion, err := h.cfg.AccessPoint.GetAutoUpdateVersion(r.Context())
// TODO(vapopov) DELETE IN v18.0.0 check of IsNotImplemented, must be backported to all latest supported versions.
if err != nil && !trace.IsNotFound(err) && !trace.IsNotImplemented(err) {
h.log.WithError(err).Error("failed to receive AutoUpdateVersion")
} else if err == nil {
response.AutoUpdate.ToolsVersion = autoUpdateVersion.GetSpec().GetToolsVersion()
response.AutoUpdate.ToolsVersion = autoUpdateVersion.GetSpec().GetTools().GetTargetVersion()
}

return response, nil
Expand Down
Loading

0 comments on commit 6ddfd56

Please sign in to comment.