cmd/kgctl: add output options for showconf

This commit adds several output options to the `showconf` command of the
`kgctl` binary:
* `--as-peer`: this can be used to generate a peer configuration, which
can be used to configure the selected resource as a peer of another
WireGuard interface
* `--output`: this can be used to select the desired output format of
the peer resource, available options are: WireGuard, YAML, and JSON.
This commit is contained in:
Lucas Servén Marín
2019-05-08 01:31:36 +02:00
parent 5914a9468f
commit 90e68c7735
5 changed files with 185 additions and 17 deletions

View File

@@ -25,7 +25,6 @@ func graph() *cobra.Command {
return &cobra.Command{
Use: "graph",
Short: "Generates a graph of the Kilo network",
Long: "",
RunE: runGraph,
}
}

View File

@@ -17,16 +17,42 @@ package main
import (
"errors"
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"github.com/squat/kilo/pkg/k8s/apis/kilo/v1alpha1"
"github.com/squat/kilo/pkg/mesh"
"github.com/squat/kilo/pkg/wireguard"
)
const (
outputFormatJSON = "json"
outputFormatWireGuard = "wireguard"
outputFormatYAML = "yaml"
)
var (
availableOutputFormats = strings.Join([]string{
outputFormatJSON,
outputFormatWireGuard,
outputFormatYAML,
}, ", ")
asPeer bool
output string
serializer *json.Serializer
)
func showConf() *cobra.Command {
cmd := &cobra.Command{
Use: "showconf",
Short: "Show the WireGuard configuration for a node or peer in the Kilo network",
Long: "",
Use: "showconf",
Short: "Show the WireGuard configuration for a node or peer in the Kilo network",
PersistentPreRunE: runShowConf,
}
for _, subCmd := range []*cobra.Command{
@@ -35,15 +61,29 @@ func showConf() *cobra.Command {
} {
cmd.AddCommand(subCmd)
}
cmd.PersistentFlags().BoolVar(&asPeer, "as-peer", false, "Should the resource be shown as a peer? Useful to configure this resource as a peer of another WireGuard interface.")
cmd.PersistentFlags().StringVarP(&output, "output", "o", "wireguard", fmt.Sprintf("The output format of the resource. Only valid when combined with 'as-peer'. Possible values: %s", availableOutputFormats))
return cmd
}
func runShowConf(c *cobra.Command, args []string) error {
switch output {
case outputFormatJSON:
serializer = json.NewSerializer(json.DefaultMetaFactory, peerCreatorTyper{}, peerCreatorTyper{}, true)
case outputFormatWireGuard:
case outputFormatYAML:
serializer = json.NewYAMLSerializer(json.DefaultMetaFactory, peerCreatorTyper{}, peerCreatorTyper{})
default:
return fmt.Errorf("output format %v unknown; posible values are: %s", output, availableOutputFormats)
}
return runRoot(c, args)
}
func showConfNode() *cobra.Command {
return &cobra.Command{
Use: "node",
Use: "node [name]",
Short: "Show the WireGuard configuration for a node in the Kilo network",
Long: "",
RunE: runShowConfNode,
Args: cobra.ExactArgs(1),
}
@@ -51,9 +91,8 @@ func showConfNode() *cobra.Command {
func showConfPeer() *cobra.Command {
return &cobra.Command{
Use: "peer",
Use: "peer [name]",
Short: "Show the WireGuard configuration for a peer in the Kilo network",
Long: "",
RunE: runShowConfPeer,
Args: cobra.ExactArgs(1),
}
@@ -93,11 +132,35 @@ func runShowConfNode(_ *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("failed to create topology: %v", err)
}
c, err := t.Conf().Bytes()
if err != nil {
return fmt.Errorf("failed to generate configuration: %v", err)
if !asPeer {
c, err := t.Conf().Bytes()
if err != nil {
return fmt.Errorf("failed to generate configuration: %v", err)
}
_, err = os.Stdout.Write(c)
return err
}
switch output {
case outputFormatJSON:
fallthrough
case outputFormatYAML:
p := translatePeer(t.AsPeer())
p.Name = hostname
return serializer.Encode(p, os.Stdout)
case outputFormatWireGuard:
c, err := (&wireguard.Conf{
Peers: []*wireguard.Peer{
t.AsPeer(),
},
}).Bytes()
if err != nil {
return fmt.Errorf("failed to generate configuration: %v", err)
}
_, err = os.Stdout.Write(c)
return err
}
fmt.Printf(string(c))
return nil
}
@@ -137,10 +200,89 @@ func runShowConfPeer(_ *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("failed to create topology: %v", err)
}
c, err := t.PeerConf(peer).Bytes()
if err != nil {
return fmt.Errorf("failed to generate configuration: %v", err)
if !asPeer {
c, err := t.PeerConf(peer).Bytes()
if err != nil {
return fmt.Errorf("failed to generate configuration: %v", err)
}
_, err = os.Stdout.Write(c)
return err
}
switch output {
case outputFormatJSON:
fallthrough
case outputFormatYAML:
p := translatePeer(t.AsPeer())
p.Name = peer
return serializer.Encode(p, os.Stdout)
case outputFormatWireGuard:
c, err := (&wireguard.Conf{
Peers: []*wireguard.Peer{
&peers[peer].Peer,
},
}).Bytes()
if err != nil {
return fmt.Errorf("failed to generate configuration: %v", err)
}
_, err = os.Stdout.Write(c)
return err
}
fmt.Printf(string(c))
return nil
}
// translatePeer translates a wireguard.Peer to a Peer CRD.
func translatePeer(peer *wireguard.Peer) *v1alpha1.Peer {
if peer == nil {
return &v1alpha1.Peer{}
}
var aips []string
for _, aip := range peer.AllowedIPs {
// Skip any invalid IPs.
if aip == nil {
continue
}
aips = append(aips, aip.String())
}
var endpoint *v1alpha1.PeerEndpoint
if peer.Endpoint != nil && peer.Endpoint.Port > 0 && peer.Endpoint.IP != nil {
endpoint = &v1alpha1.PeerEndpoint{
IP: peer.Endpoint.IP.String(),
Port: peer.Endpoint.Port,
}
}
var key string
if len(peer.PublicKey) > 0 {
key = string(peer.PublicKey)
}
var pka int
if peer.PersistentKeepalive > 0 {
pka = peer.PersistentKeepalive
}
return &v1alpha1.Peer{
TypeMeta: metav1.TypeMeta{
Kind: v1alpha1.PeerKind,
APIVersion: v1alpha1.SchemeGroupVersion.String(),
},
Spec: v1alpha1.PeerSpec{
AllowedIPs: aips,
Endpoint: endpoint,
PublicKey: key,
PersistentKeepalive: pka,
},
}
}
type peerCreatorTyper struct{}
func (p peerCreatorTyper) New(_ schema.GroupVersionKind) (runtime.Object, error) {
return &v1alpha1.Peer{}, nil
}
func (p peerCreatorTyper) ObjectKinds(_ runtime.Object) ([]schema.GroupVersionKind, bool, error) {
return []schema.GroupVersionKind{v1alpha1.PeerGVK}, false, nil
}
func (p peerCreatorTyper) Recognizes(_ schema.GroupVersionKind) bool {
return true
}