Skip to content

Commit

Permalink
fix(engine): reorganize packages
Browse files Browse the repository at this point in the history
  • Loading branch information
nicklasfrahm committed Apr 18, 2022
1 parent 97a9aab commit f3231ea
Show file tree
Hide file tree
Showing 14 changed files with 390 additions and 340 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# k3se 🧀

A lightweight Kubernetes engine that deploys `k3s` clusters declaratively based on a cluster configuration file.

The name is a hommage to the German word for cheese, _Käse [ˈkɛːzə]_.
A lightweight Kubernetes engine that deploys `k3s` clusters declaratively based on a cluster configuration file. The name is a hommage to the German word for cheese, _Käse [ˈkɛːzə]_.

## License 📄

Expand Down
6 changes: 3 additions & 3 deletions cmd/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package cmd
import (
"github.com/spf13/cobra"

"github.com/nicklasfrahm/k3se/pkg/k3se"
"github.com/nicklasfrahm/k3se/pkg/ops"
)

var upCmd = &cobra.Command{
Expand All @@ -19,10 +19,10 @@ argument.`,
RunE: func(cmd *cobra.Command, args []string) error {
// Use manual override for config path if provided.
if len(args) == 1 {
return k3se.Up(k3se.WithConfigPath(args[0]))
return ops.Up(ops.WithConfigPath(args[0]))
}

return k3se.Up()
return ops.Up()
},
}

Expand Down
4 changes: 2 additions & 2 deletions examples/standalone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ cluster:
- kubeapi.example.com
disable:
- traefik
write-kubeconfig-mode: "0644"
write-kubeconfig-mode: "644"

# A list of all nodes in the cluster and their connection information.
nodes:
- role: server
ssh:
host: 192.168.254.254
host: 127.0.0.1
fingerprint: SHA256:t/bwWCelgcAEYmQW9XbM4p31e1Qq70ZPWOKK+FRxBCc
user: nicklasfrahm
key-file: ~/.ssh/id_ed25519
Expand Down
81 changes: 37 additions & 44 deletions pkg/k3se/config.go → pkg/engine/config.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
package k3se
package engine

import (
"errors"
"fmt"
"io/ioutil"

"github.com/nicklasfrahm/k3se/pkg/rexec"
"github.com/nicklasfrahm/k3se/pkg/sshx"
"gopkg.in/yaml.v3"
)

// Role is the type of a node in the cluster.
type Role string

const (
// RoleAny is the role selector that matches any node.
RoleAny Role = "any"
// RoleServer is the role of a control-plane node in k3s.
RoleServer = "server"
RoleServer Role = "server"
// RoleAgent is the role of a worker node in k3s.
RoleAgent = "agent"
// Program is used to configure the name of the configuration file.
Program = "k3se"
RoleAgent Role = "agent"
)

// Node describes the configuration of a node.
type Node struct {
Role string `yaml:"role"`
SSH rexec.SSHConfig `yaml:"ssh"`
NodeLabel []string `yaml:"node-label"`
}

// K3sConfig describes the configuration of a k3s node.
type K3sConfig struct {
WriteKubeconfigMode string `yaml:"write-kubeconfig-mode"`
Expand All @@ -40,67 +35,65 @@ type Config struct {
// channel as specified in the k3s installation options.
Version string `yaml:"version"`

// Config is the desired content of the k3s configuration file.
// Config is the desired content of the k3s configuration file
// that is shared among all nodes.
Cluster K3sConfig `yaml:"config"`

// Nodes is a list of nodes to deploy the cluster on.
// Nodes is a list of nodes to deploy the cluster on. It stores
// both, connection information and node-specific configuration.
Nodes []Node `yaml:"nodes"`

// SSHProxy describes the SSH connection configuration
// for an SSH proxy, often also referred to as bastion
// host or jumpbox.
SSHProxy rexec.SSHConfig `yaml:"ssh-proxy"`
SSHProxy sshx.Config `yaml:"ssh-proxy"`
}

// Verify verifies the configuration file.
// TODO: How do we pass a logger to this function?
// TODO: Use logger to display configuration errors.
func (c *Config) Verify() error {
if c == nil {
return errors.New("configuration empty")
}

checks := []func() error{
c.VerifyServerCount,
if c.Nodes == nil || len(c.Nodes) == 0 {
return errors.New("no nodes specified")
}

var configInvalid bool
for _, check := range checks {
if err := check(); err != nil {
configInvalid = true

// TODO: Improve how errors are displayed and handled.
fmt.Println(err)
var controlPlanes = 0
for _, node := range c.Nodes {
if node.Role == RoleServer {
controlPlanes += 1
}
}

if configInvalid {
return errors.New("config invalid")
if controlPlanes == 0 {
return errors.New("no control-plane nodes specified")
}

// TODO: Check that backend is not SQLite if HA is enabled.
if controlPlanes > 1 {
return errors.New("unimplemented: multiple control-plane nodes")

// TODO: Check that backend is not SQLite if HA is enabled.
}

return nil
}

// VerifyServerCount verifies that at least one API server is
// specified.
func (c *Config) VerifyServerCount() error {
var controlPlanes = 0

if c.Nodes == nil || len(c.Nodes) == 0 {
return errors.New("no nodes specified")
}
// NodesByRole returns a list of nodes based on the specified selector.
// Use RoleAny to match all nodes, RoleAgent to match all worker nodes,
// and RoleServer to match all control-plane nodes.
func (c *Config) NodesByRole(selector Role) []*Node {
var nodes []*Node

for _, node := range c.Nodes {
if node.Role == RoleServer {
controlPlanes += 1
if node.Role == selector || selector == RoleAny {
nodes = append(nodes, &node)
}
}

if controlPlanes == 0 {
return errors.New("no control-plane nodes specified")
}

return nil
return nodes
}

// LoadConfig sets up the configuration parser and loads
Expand Down
41 changes: 41 additions & 0 deletions pkg/engine/node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package engine

import "github.com/nicklasfrahm/k3se/pkg/sshx"

const (
// Program is used to configure the name of the configuration file.
Program = "k3se"
)

// Node describes the configuration of a node.
type Node struct {
Role Role `yaml:"role"`
SSH sshx.Config `yaml:"ssh"`
NodeLabel []string `yaml:"node-label"`

*sshx.Client `yaml:"-"`
}

// Connect establishes a connection to the node.
func (node *Node) Connect(options ...Option) error {
opts, err := GetDefaultOptions().Apply(options...)
if err != nil {
return err
}

node.Client, err = sshx.NewClient(&node.SSH,
sshx.WithProxy(opts.SSHProxy),
sshx.WithLogger(opts.Logger),
sshx.WithTimeout(opts.Timeout),
)
if err != nil {
return err
}

return nil
}

// Disconnect closes the connection to the node.
func (node *Node) Disconnect() error {
return nil
}
29 changes: 24 additions & 5 deletions pkg/rexec/options.go → pkg/engine/options.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package rexec
package engine

import (
"os"
"time"

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"

"github.com/nicklasfrahm/k3se/pkg/sshx"
)

// Options contains the configuration for an operation.
type Options struct {
Logger *zerolog.Logger
SSHProxy *SSHConfig
SSHProxy *sshx.Client
Timeout time.Duration
}

Expand Down Expand Up @@ -44,10 +46,27 @@ func GetDefaultOptions() *Options {
}
}

// WithSSHProxy configures an SSH bastion host.
func WithSSHProxy(sshProxy *SSHConfig) Option {
// WithLogger allows to use a custom logger.
func WithLogger(logger *zerolog.Logger) Option {
return func(options *Options) error {
options.Logger = logger
return nil
}
}

// WithSSHProxy allows to use an existing SSH
// connection as an SSH bastion host.
func WithSSHProxy(proxy *sshx.Client) Option {
return func(options *Options) error {
options.SSHProxy = proxy
return nil
}
}

// WithTimeout allows to set a custom timeout.
func WithTimeout(timeout time.Duration) Option {
return func(options *Options) error {
options.SSHProxy = sshProxy
options.Timeout = timeout
return nil
}
}
57 changes: 0 additions & 57 deletions pkg/k3se/up.go

This file was deleted.

2 changes: 1 addition & 1 deletion pkg/k3se/diff.go → pkg/ops/diff.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package k3se
package ops

import (
"errors"
Expand Down
7 changes: 6 additions & 1 deletion pkg/k3se/options.go → pkg/ops/options.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
package k3se
package ops

const (
// Program is used to configure the name of the configuration file.
Program = "k3se"
)

// Options contains the configuration for an operation.
type Options struct {
Expand Down
Loading

0 comments on commit f3231ea

Please sign in to comment.