-
Notifications
You must be signed in to change notification settings - Fork 550
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement resource API in Talos
This brings in `os-runtime` package and exposes resources with first iteration of read-only API. Two Talos resources (and one controller) are implemented: * legacy.Service resource tracks Talos 'service' `RUNNING` state * config.V1Alpha1 stores current runtime config Glue point between existing runtime and new os-runtime based runtime is in `v1alpha2` implementation and `V1Alpha2()` sub-interfaces of existing `Runtime`, `State`, `Controller` interfaces. Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
- Loading branch information
Showing
37 changed files
with
2,704 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
syntax = "proto3"; | ||
|
||
package resource; | ||
|
||
option go_package = "github.com/talos-systems/talos/pkg/machinery/api/resource"; | ||
option java_multiple_files = true; | ||
option java_outer_classname = "ResourceApi"; | ||
option java_package = "com.resource.api"; | ||
|
||
import "common/common.proto"; | ||
|
||
// The resource service definition. | ||
// | ||
// ResourceService provides user-facing API for the Talos resources. | ||
service ResourceService { | ||
rpc Get(GetRequest) returns (GetResponse); | ||
rpc List(ListRequest) returns (stream ListResponse); | ||
rpc Watch(WatchRequest) returns (stream WatchResponse); | ||
} | ||
|
||
// common resource definition | ||
|
||
message Resource { | ||
Metadata metadata = 1; | ||
Spec spec = 2; | ||
} | ||
|
||
message Metadata { | ||
string namespace = 1; | ||
string type = 2; | ||
string id = 3; | ||
string version = 4; | ||
string phase = 5; | ||
repeated string finalizers = 6; | ||
} | ||
|
||
message Spec { | ||
bytes yaml = 1; | ||
} | ||
|
||
// rpc Get | ||
message GetRequest { | ||
string namespace = 1; | ||
string type = 2; | ||
string id = 3; | ||
} | ||
|
||
// The GetResponse message contains the Resource returned. | ||
message Get { | ||
common.Metadata metadata = 1; | ||
Resource definition = 2; | ||
Resource resource = 3; | ||
} | ||
|
||
message GetResponse { repeated Get messages = 1; } | ||
|
||
// rpc List | ||
// The ListResponse message contains the Resource returned. | ||
message ListRequest { | ||
string namespace = 1; | ||
string type = 2; | ||
} | ||
|
||
message ListResponse { | ||
common.Metadata metadata = 1; | ||
Resource definition = 2; | ||
Resource resource = 3; | ||
} | ||
|
||
// rpc Watch | ||
// The WatchResponse message contains the Resource returned. | ||
message WatchRequest {} | ||
|
||
enum EventType { | ||
CREATED = 0; | ||
UPDATED = 1; | ||
DELETED = 2; | ||
} | ||
|
||
message WatchResponse { | ||
common.Metadata metadata = 1; | ||
EventType event_type = 2; | ||
Resource resource = 3; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
package talos | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/status" | ||
|
||
"github.com/talos-systems/talos/cmd/talosctl/cmd/talos/output" | ||
"github.com/talos-systems/talos/pkg/machinery/client" | ||
) | ||
|
||
var getCmdFlags struct { | ||
namespace string | ||
|
||
output string | ||
} | ||
|
||
// getCmd represents the get (resources) command. | ||
var getCmd = &cobra.Command{ | ||
Use: "get <type> [<id>]", | ||
Aliases: []string{"g"}, | ||
Short: "Get a specific resource or list of resources.", | ||
Long: ``, | ||
Args: cobra.RangeArgs(1, 2), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return WithClient(func(ctx context.Context, c *client.Client) error { | ||
out, err := output.NewWriter(getCmdFlags.output) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
resourceType := args[0] | ||
|
||
var resourceID string | ||
|
||
if len(args) == 2 { | ||
resourceID = args[1] | ||
} | ||
|
||
defer out.Flush() //nolint: errcheck | ||
|
||
var headerWritten bool | ||
|
||
if resourceID != "" { | ||
resp, err := c.Resources.Get(ctx, getCmdFlags.namespace, resourceType, resourceID) | ||
|
||
for _, msg := range resp { | ||
if msg.Definition != nil && !headerWritten { | ||
if e := out.WriteHeader(msg.Definition); e != nil { | ||
return e | ||
} | ||
|
||
headerWritten = true | ||
} | ||
|
||
if msg.Resource != nil { | ||
if e := out.WriteResource(msg.Metadata.GetHostname(), msg.Resource); e != nil { | ||
return e | ||
} | ||
} | ||
|
||
} | ||
|
||
if err != nil { | ||
return err | ||
} | ||
} else { | ||
listClient, err := c.Resources.List(ctx, getCmdFlags.namespace, resourceType) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for { | ||
msg, err := listClient.Recv() | ||
if err != nil { | ||
if err == io.EOF || status.Code(err) == codes.Canceled { | ||
return nil | ||
} | ||
|
||
return err | ||
} | ||
|
||
if msg.Metadata.GetError() != "" { | ||
fmt.Fprintf(os.Stderr, "%s: %s\n", msg.Metadata.GetHostname(), msg.Metadata.GetError()) | ||
|
||
continue | ||
} | ||
|
||
if msg.Definition != nil && !headerWritten { | ||
if e := out.WriteHeader(msg.Definition); e != nil { | ||
return e | ||
} | ||
|
||
headerWritten = true | ||
} | ||
|
||
if msg.Resource != nil { | ||
if err := out.WriteResource(msg.Metadata.GetHostname(), msg.Resource); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
}) | ||
}, | ||
} | ||
|
||
func init() { | ||
getCmd.Flags().StringVar(&getCmdFlags.namespace, "namespace", "", "resource namespace (default is to use default namespace per resource)") | ||
getCmd.Flags().StringVarP(&getCmdFlags.output, "output", "o", "table", "output mode (table, yaml)") | ||
addCommand(getCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
// Package output provides writers in different formats. | ||
package output | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/talos-systems/os-runtime/pkg/resource" | ||
) | ||
|
||
// Writer interface. | ||
type Writer interface { | ||
WriteHeader(definition resource.Resource) error | ||
WriteResource(node string, r resource.Resource) error | ||
Flush() error | ||
} | ||
|
||
// NewWriter builds writer from type. | ||
func NewWriter(format string) (Writer, error) { | ||
switch format { | ||
case "table": | ||
return NewTable(), nil | ||
case "yaml": | ||
return NewYAML(), nil | ||
default: | ||
return nil, fmt.Errorf("output format %q is not supported", format) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
package output | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"text/tabwriter" | ||
|
||
"github.com/talos-systems/os-runtime/pkg/resource" | ||
) | ||
|
||
// Table outputs resources in Table view. | ||
type Table struct { | ||
w tabwriter.Writer | ||
} | ||
|
||
// NewTable initializes table resource output. | ||
func NewTable() *Table { | ||
output := &Table{} | ||
output.w.Init(os.Stdout, 0, 0, 3, ' ', 0) | ||
|
||
return output | ||
} | ||
|
||
// WriteHeader implements output.Writer interface. | ||
func (table *Table) WriteHeader(definition resource.Resource) error { | ||
_, err := fmt.Fprintln(&table.w, "NODE\tNAMESPACE\tTYPE\tID") | ||
|
||
return err | ||
} | ||
|
||
// WriteResource implements output.Writer interface. | ||
func (table *Table) WriteResource(node string, r resource.Resource) error { | ||
_, err := fmt.Fprintf(&table.w, "%s\t%s\t%s\t%s\n", node, r.Metadata().Namespace(), r.Metadata().Type(), r.Metadata().ID()) | ||
|
||
return err | ||
} | ||
|
||
// Flush implements output.Writer interface. | ||
func (table *Table) Flush() error { | ||
return table.w.Flush() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
package output | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/talos-systems/os-runtime/pkg/resource" | ||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
// YAML outputs resources in YAML format. | ||
type YAML struct { | ||
needDashes bool | ||
} | ||
|
||
// NewYAML initializes YAML resource output. | ||
func NewYAML() *YAML { | ||
return &YAML{} | ||
} | ||
|
||
// WriteHeader implements output.Writer interface. | ||
func (y *YAML) WriteHeader(definition resource.Resource) error { | ||
return nil | ||
} | ||
|
||
// WriteResource implements output.Writer interface. | ||
func (y *YAML) WriteResource(node string, r resource.Resource) error { | ||
out, err := resource.MarshalYAML(r) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if y.needDashes { | ||
fmt.Fprintln(os.Stdout, "---") | ||
} | ||
|
||
y.needDashes = true | ||
|
||
fmt.Fprintf(os.Stdout, "node: %s\n", node) | ||
|
||
return yaml.NewEncoder(os.Stdout).Encode(out) | ||
} | ||
|
||
// Flush implements output.Writer interface. | ||
func (y *YAML) Flush() error { | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.