Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client AutoUpdate proto structure changes #47532

Merged
merged 6 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/client/webclient/webclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,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
228 changes: 170 additions & 58 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 == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you no longer validate v.Spec.ToolsVersion. Is it used in prod? Should we keep it if not used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually we decided to rename before actual usage in prod, so this resource is not used previously

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 @@ -3981,7 +3981,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 @@ -3991,7 +3993,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 @@ -72,10 +76,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 @@ -107,7 +113,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 @@ -128,10 +138,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 @@ -163,7 +175,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 @@ -174,7 +190,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 @@ -196,7 +216,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 @@ -209,7 +233,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 @@ -1545,15 +1545,15 @@ func (h *Handler) find(w http.ResponseWriter, r *http.Request, p httprouter.Para
if err != nil && !trace.IsNotFound(err) && !trace.IsNotImplemented(err) {
h.logger.ErrorContext(r.Context(), "failed to receive AutoUpdateConfig", "error", err)
} 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.logger.ErrorContext(r.Context(), "failed to receive AutoUpdateVersion", "error", err)
} else if err == nil {
response.AutoUpdate.ToolsVersion = autoUpdateVersion.GetSpec().GetToolsVersion()
response.AutoUpdate.ToolsVersion = autoUpdateVersion.GetSpec().GetTools().GetTargetVersion()
}

return response, nil
Expand Down
Loading
Loading