Skip to content

Commit

Permalink
Add tctl resource commands for AutoUpdateConfig and AutoUpdateVersion (
Browse files Browse the repository at this point in the history
…#46771) (#46866)

* Add autoupdate command for resource

* Reuse client methods

* Implement all exposed auto update methods for service client

* Fix linter
  • Loading branch information
vapopov authored Oct 2, 2024
1 parent d68fd7a commit cbfa8b8
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 0 deletions.
86 changes: 86 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2719,6 +2719,18 @@ func (c *Client) GetClusterAuditConfig(ctx context.Context) (types.ClusterAuditC
return resp, nil
}

// CreateAutoUpdateConfig creates AutoUpdateConfig resource.
func (c *Client) CreateAutoUpdateConfig(ctx context.Context, config *autoupdatev1pb.AutoUpdateConfig) (*autoupdatev1pb.AutoUpdateConfig, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.CreateAutoUpdateConfig(ctx, &autoupdatev1pb.CreateAutoUpdateConfigRequest{
Config: config,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// GetAutoUpdateConfig gets AutoUpdateConfig resource.
func (c *Client) GetAutoUpdateConfig(ctx context.Context) (*autoupdatev1pb.AutoUpdateConfig, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
Expand All @@ -2729,6 +2741,49 @@ func (c *Client) GetAutoUpdateConfig(ctx context.Context) (*autoupdatev1pb.AutoU
return resp, nil
}

// UpdateAutoUpdateConfig updates AutoUpdateConfig resource.
func (c *Client) UpdateAutoUpdateConfig(ctx context.Context, config *autoupdatev1pb.AutoUpdateConfig) (*autoupdatev1pb.AutoUpdateConfig, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.UpdateAutoUpdateConfig(ctx, &autoupdatev1pb.UpdateAutoUpdateConfigRequest{
Config: config,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// UpsertAutoUpdateConfig updates or creates AutoUpdateConfig resource.
func (c *Client) UpsertAutoUpdateConfig(ctx context.Context, config *autoupdatev1pb.AutoUpdateConfig) (*autoupdatev1pb.AutoUpdateConfig, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.UpsertAutoUpdateConfig(ctx, &autoupdatev1pb.UpsertAutoUpdateConfigRequest{
Config: config,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// DeleteAutoUpdateConfig deletes AutoUpdateConfig resource.
func (c *Client) DeleteAutoUpdateConfig(ctx context.Context) error {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
_, err := client.DeleteAutoUpdateConfig(ctx, &autoupdatev1pb.DeleteAutoUpdateConfigRequest{})
return trace.Wrap(err)
}

// CreateAutoUpdateVersion creates AutoUpdateVersion resource.
func (c *Client) CreateAutoUpdateVersion(ctx context.Context, version *autoupdatev1pb.AutoUpdateVersion) (*autoupdatev1pb.AutoUpdateVersion, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.CreateAutoUpdateVersion(ctx, &autoupdatev1pb.CreateAutoUpdateVersionRequest{
Version: version,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// GetAutoUpdateVersion gets AutoUpdateVersion resource.
func (c *Client) GetAutoUpdateVersion(ctx context.Context) (*autoupdatev1pb.AutoUpdateVersion, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
Expand All @@ -2739,6 +2794,37 @@ func (c *Client) GetAutoUpdateVersion(ctx context.Context) (*autoupdatev1pb.Auto
return resp, nil
}

// UpdateAutoUpdateVersion updates AutoUpdateVersion resource.
func (c *Client) UpdateAutoUpdateVersion(ctx context.Context, version *autoupdatev1pb.AutoUpdateVersion) (*autoupdatev1pb.AutoUpdateVersion, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.UpdateAutoUpdateVersion(ctx, &autoupdatev1pb.UpdateAutoUpdateVersionRequest{
Version: version,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// UpsertAutoUpdateVersion updates or creates AutoUpdateVersion resource.
func (c *Client) UpsertAutoUpdateVersion(ctx context.Context, version *autoupdatev1pb.AutoUpdateVersion) (*autoupdatev1pb.AutoUpdateVersion, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.UpsertAutoUpdateVersion(ctx, &autoupdatev1pb.UpsertAutoUpdateVersionRequest{
Version: version,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// DeleteAutoUpdateVersion deletes AutoUpdateVersion resource.
func (c *Client) DeleteAutoUpdateVersion(ctx context.Context) error {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
_, err := client.DeleteAutoUpdateVersion(ctx, &autoupdatev1pb.DeleteAutoUpdateVersionRequest{})
return trace.Wrap(err)
}

// GetClusterAccessGraphConfig retrieves the Cluster Access Graph configuration from Auth server.
func (c *Client) GetClusterAccessGraphConfig(ctx context.Context) (*clusterconfigpb.AccessGraphConfig, error) {
rsp, err := c.ClusterConfigClient().GetClusterAccessGraphConfig(ctx, &clusterconfigpb.GetClusterAccessGraphConfigRequest{})
Expand Down
4 changes: 4 additions & 0 deletions lib/services/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,10 @@ func ParseShortcut(in string) (string, error) {
return types.KindServerInfo, nil
case types.KindAccessRequest, types.KindAccessRequest + "s", "accessrequest", "accessrequests":
return types.KindAccessRequest, nil
case types.KindAutoUpdateConfig:
return types.KindAutoUpdateConfig, nil
case types.KindAutoUpdateVersion:
return types.KindAutoUpdateVersion, nil
}
return "", trace.BadParameter("unsupported resource: %q - resources should be expressed as 'type/name', for example 'connector/github'", in)
}
Expand Down
37 changes: 37 additions & 0 deletions tool/tctl/common/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/constants"
autoupdatev1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/autoupdate/v1"
devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1"
loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1"
"github.com/gravitational/teleport/api/types"
Expand Down Expand Up @@ -1384,3 +1385,39 @@ func (c *accessRequestCollection) writeText(w io.Writer, verbose bool) error {
_, err := t.AsBuffer().WriteTo(w)
return trace.Wrap(err)
}

type autoUpdateConfigCollection struct {
config *autoupdatev1pb.AutoUpdateConfig
}

func (c *autoUpdateConfigCollection) resources() []types.Resource {
return []types.Resource{types.Resource153ToLegacy(c.config)}
}

func (c *autoUpdateConfigCollection) writeText(w io.Writer, verbose bool) error {
t := asciitable.MakeTable([]string{"Name", "Tools AutoUpdate Enabled"})
t.AddRow([]string{
c.config.GetMetadata().GetName(),
fmt.Sprintf("%v", c.config.GetSpec().GetToolsAutoupdate()),
})
_, err := t.AsBuffer().WriteTo(w)
return trace.Wrap(err)
}

type autoUpdateVersionCollection struct {
version *autoupdatev1pb.AutoUpdateVersion
}

func (c *autoUpdateVersionCollection) resources() []types.Resource {
return []types.Resource{types.Resource153ToLegacy(c.version)}
}

func (c *autoUpdateVersionCollection) writeText(w io.Writer, verbose bool) error {
t := asciitable.MakeTable([]string{"Name", "Tools AutoUpdate Version"})
t.AddRow([]string{
c.version.GetMetadata().GetName(),
fmt.Sprintf("%v", c.version.GetSpec().GetToolsVersion()),
})
_, err := t.AsBuffer().WriteTo(w)
return trace.Wrap(err)
}
53 changes: 53 additions & 0 deletions tool/tctl/common/resource_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
apiclient "github.com/gravitational/teleport/api/client"
"github.com/gravitational/teleport/api/client/proto"
apidefaults "github.com/gravitational/teleport/api/defaults"
autoupdatev1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/autoupdate/v1"
devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1"
loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1"
"github.com/gravitational/teleport/api/internalutils/stream"
Expand Down Expand Up @@ -141,6 +142,8 @@ func (rc *ResourceCommand) Initialize(app *kingpin.Application, config *servicec
types.KindAuditQuery: rc.createAuditQuery,
types.KindSecurityReport: rc.createSecurityReport,
types.KindServerInfo: rc.createServerInfo,
types.KindAutoUpdateConfig: rc.createAutoUpdateConfig,
types.KindAutoUpdateVersion: rc.createAutoUpdateVersion,
}
rc.config = config

Expand Down Expand Up @@ -2380,6 +2383,18 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient
case types.KindAccessRequest:
resource, err := client.GetAccessRequests(ctx, types.AccessRequestFilter{ID: rc.ref.Name})
return &accessRequestCollection{accessRequests: resource}, trace.Wrap(err)
case types.KindAutoUpdateConfig:
config, err := client.GetAutoUpdateConfig(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
return &autoUpdateConfigCollection{config}, nil
case types.KindAutoUpdateVersion:
version, err := client.GetAutoUpdateVersion(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
return &autoUpdateVersionCollection{version}, nil
}
return nil, trace.BadParameter("getting %q is not supported", rc.ref.String())
}
Expand Down Expand Up @@ -2604,3 +2619,41 @@ func (rc *ResourceCommand) createSecurityReport(ctx context.Context, client *aut
}
return nil
}

func (rc *ResourceCommand) createAutoUpdateConfig(ctx context.Context, client *authclient.Client, raw services.UnknownResource) error {
config, err := services.UnmarshalProtoResource[*autoupdatev1pb.AutoUpdateConfig](raw.Raw)
if err != nil {
return trace.Wrap(err)
}

if rc.IsForced() {
_, err = client.UpsertAutoUpdateConfig(ctx, config)
} else {
_, err = client.CreateAutoUpdateConfig(ctx, config)
}
if err != nil {
return trace.Wrap(err)
}

fmt.Println("autoupdate_config has been created")
return nil
}

func (rc *ResourceCommand) createAutoUpdateVersion(ctx context.Context, client *authclient.Client, raw services.UnknownResource) error {
version, err := services.UnmarshalProtoResource[*autoupdatev1pb.AutoUpdateVersion](raw.Raw)
if err != nil {
return trace.Wrap(err)
}

if rc.IsForced() {
_, err = client.UpsertAutoUpdateVersion(ctx, version)
} else {
_, err = client.CreateAutoUpdateVersion(ctx, version)
}
if err != nil {
return trace.Wrap(err)
}

fmt.Println("autoupdate_version has been created")
return nil
}
81 changes: 81 additions & 0 deletions tool/tctl/common/resource_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ import (
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/testing/protocmp"
"k8s.io/apimachinery/pkg/util/yaml"

"github.com/gravitational/teleport/api/constants"
apidefaults "github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/teleport/api/gen/proto/go/teleport/autoupdate/v1"
headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/discoveryconfig"
"github.com/gravitational/teleport/api/types/header"
Expand Down Expand Up @@ -1355,6 +1358,14 @@ func TestCreateResources(t *testing.T) {
kind: types.KindServerInfo,
create: testCreateServerInfo,
},
{
kind: types.KindAutoUpdateConfig,
create: testCreateAutoUpdateConfig,
},
{
kind: types.KindAutoUpdateVersion,
create: testCreateAutoUpdateVersion,
},
}

for _, test := range tests {
Expand Down Expand Up @@ -1418,3 +1429,73 @@ spec:
_, err = runResourceCommand(t, fc, []string{"create", "-f", serverInfoYAMLPath})
require.NoError(t, err)
}

func testCreateAutoUpdateConfig(t *testing.T, fc *config.FileConfig) {
const resourceYAML = `kind: autoupdate_config
metadata:
name: autoupdate-config
revision: 3a43b44a-201e-4d7f-aef1-ae2f6d9811ed
spec:
tools_autoupdate: true
version: v1
`
_, err := runResourceCommand(t, fc, []string{"get", types.KindAutoUpdateConfig, "--format=json"})
require.ErrorContains(t, err, "doesn't exist")

// Create the resource.
resourceYAMLPath := filepath.Join(t.TempDir(), "resource.yaml")
require.NoError(t, os.WriteFile(resourceYAMLPath, []byte(resourceYAML), 0644))
_, err = runResourceCommand(t, fc, []string{"create", resourceYAMLPath})
require.NoError(t, err)

// Get the resource
buf, err := runResourceCommand(t, fc, []string{"get", types.KindAutoUpdateConfig, "--format=json"})
require.NoError(t, err)
resources := mustDecodeJSON[[]*autoupdate.AutoUpdateConfig](t, buf)
require.Len(t, resources, 1)

var expected autoupdate.AutoUpdateConfig
require.NoError(t, yaml.Unmarshal([]byte(resourceYAML), &expected))

require.Empty(t, cmp.Diff(
[]*autoupdate.AutoUpdateConfig{&expected},
resources,
protocmp.IgnoreFields(&headerv1.Metadata{}, "id", "revision"),
protocmp.Transform(),
))
}

func testCreateAutoUpdateVersion(t *testing.T, fc *config.FileConfig) {
const resourceYAML = `kind: autoupdate_version
metadata:
name: autoupdate-version
revision: 3a43b44a-201e-4d7f-aef1-ae2f6d9811ed
spec:
tools_version: 1.2.3
version: v1
`
_, err := runResourceCommand(t, fc, []string{"get", types.KindAutoUpdateVersion, "--format=json"})
require.ErrorContains(t, err, "doesn't exist")

// Create the resource.
resourceYAMLPath := filepath.Join(t.TempDir(), "resource.yaml")
require.NoError(t, os.WriteFile(resourceYAMLPath, []byte(resourceYAML), 0644))
_, err = runResourceCommand(t, fc, []string{"create", resourceYAMLPath})
require.NoError(t, err)

// Get the resource
buf, err := runResourceCommand(t, fc, []string{"get", types.KindAutoUpdateVersion, "--format=json"})
require.NoError(t, err)
resources := mustDecodeJSON[[]*autoupdate.AutoUpdateVersion](t, buf)
require.Len(t, resources, 1)

var expected autoupdate.AutoUpdateVersion
require.NoError(t, yaml.Unmarshal([]byte(resourceYAML), &expected))

require.Empty(t, cmp.Diff(
[]*autoupdate.AutoUpdateVersion{&expected},
resources,
protocmp.IgnoreFields(&headerv1.Metadata{}, "id", "revision"),
protocmp.Transform(),
))
}

0 comments on commit cbfa8b8

Please sign in to comment.