Skip to content

Commit

Permalink
feat(engine): restructure configuration and upload install.sh
Browse files Browse the repository at this point in the history
BREAKING: The node specific configuration for k3s is now located
under its own "config" key in the YAML.

Please refer to the examples in the "examples" directory to figure
out how to modify your configuration.
  • Loading branch information
nicklasfrahm committed Apr 20, 2022
1 parent 33cb7ad commit e1612dd
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 16 deletions.
18 changes: 16 additions & 2 deletions cmd/up.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package cmd

import (
"os"
"time"

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

"github.com/nicklasfrahm/k3se/pkg/ops"
Expand All @@ -17,12 +22,21 @@ by passing a path to the configuration file as a CLI
argument.`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
logger := log.Output(zerolog.ConsoleWriter{
Out: os.Stderr,
TimeFormat: time.RFC3339,
})

opts := []ops.Option{
ops.WithLogger(&logger),
}

// Use manual override for config path if provided.
if len(args) == 1 {
return ops.Up(ops.WithConfigPath(args[0]))
opts = append(opts, ops.WithConfigPath(args[0]))
}

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

Expand Down
79 changes: 79 additions & 0 deletions pkg/engine/engine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package engine

import (
"bytes"
"io/ioutil"
"net/http"
"sync"

"github.com/rs/zerolog"
)

const (
InstallerURL = "https://get.k3s.io"
)

// Engine is a type that encapsulates parts of the installation logic.
type Engine struct {
Logger *zerolog.Logger

sync.Mutex
installer []byte
}

// New creates a new Engine.
func New(options ...Option) (*Engine, error) {
opts, err := GetDefaultOptions().Apply(options...)
if err != nil {
return nil, err
}

return &Engine{
Logger: opts.Logger,
}, nil
}

// Installer returns the downloaded the k3s installer.
func (e *Engine) Installer() ([]byte, error) {
// Lock engine to prevent concurrent access to installer cache.
e.Lock()

if len(e.installer) == 0 {
resp, err := http.Get(InstallerURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()

e.installer, err = ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
}

e.Unlock()

return e.installer, nil
}

// Configure uploads the installer and the configuration
// prior to a node prior to running the installation.
func (e *Engine) Configure(node *Node) error {
installer, err := e.Installer()
if err != nil {
return err
}

if err := node.Upload("/tmp/k3se/install.sh", bytes.NewReader(installer)); err != nil {
return err
}

// TODO: Upload configuration and move it to appropriate location using "sudo".

return nil
}

// Cleanup removes all temporary files from the node.
func (e *Engine) Cleanup(node *Node) error {
return node.Exec("rm -rf /tmp/k3se")
}
37 changes: 37 additions & 0 deletions pkg/engine/node.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package engine

import (
"io"
"path/filepath"

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

Expand Down Expand Up @@ -45,3 +48,37 @@ func (node *Node) Disconnect() error {

return nil
}

// Upload writes the specified content to the remote file on the node.
func (node *Node) Upload(dst string, src io.Reader) error {
// Get base directory for the file.
dir := filepath.Dir(dst)

// Create directory if it does not exist.
if err := node.Client.SFTP.Mkdir(dir); err != nil {
return err
}

// Upload file.
file, err := node.Client.SFTP.Create(dst)
if err != nil {
return err
}
defer file.Close()

// Empty existing file.
if err := file.Truncate(0); err != nil {
return err
}

// Overwrite file content.
_, err = io.Copy(file, src)
return err
}

// Exec executes the specified command on the node.
func (node *Node) Exec(cmd string) error {
// TODO: Implement this.

return nil
}
7 changes: 1 addition & 6 deletions pkg/engine/options.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package engine

import (
"os"
"time"

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

"github.com/nicklasfrahm/k3se/pkg/sshx"
)
Expand Down Expand Up @@ -34,10 +32,7 @@ func (o *Options) Apply(options ...Option) (*Options, error) {
// GetDefaultOptions returns the default options
// for all operations of this library.
func GetDefaultOptions() *Options {
logger := log.Output(zerolog.ConsoleWriter{
Out: os.Stderr,
TimeFormat: time.RFC3339,
})
logger := zerolog.Nop()

return &Options{
SSHProxy: nil,
Expand Down
11 changes: 11 additions & 0 deletions pkg/ops/options.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ops

import "github.com/rs/zerolog"

const (
// Program is used to configure the name of the configuration file.
Program = "k3se"
Expand All @@ -8,6 +10,7 @@ const (
// Options contains the configuration for an operation.
type Options struct {
ConfigPath string
Logger *zerolog.Logger
}

// Option applies a configuration option
Expand Down Expand Up @@ -39,3 +42,11 @@ func WithConfigPath(configPath string) Option {
return nil
}
}

// WithLogger overrides the default logger.
func WithLogger(logger *zerolog.Logger) Option {
return func(options *Options) error {
options.Logger = logger
return nil
}
}
19 changes: 17 additions & 2 deletions pkg/ops/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ func Up(options ...Option) error {
return err
}

eng, err := engine.New(engine.WithLogger(opts.Logger))
if err != nil {
return err
}

// Establish connection to proxy if host is specified.
var sshProxy *sshx.Client
if config.SSHProxy.Host != "" {
Expand All @@ -35,6 +40,10 @@ func Up(options ...Option) error {
if err := node.Connect(engine.WithSSHProxy(sshProxy)); err != nil {
return err
}

if err := eng.Configure(node); err != nil {
return err
}
}

// TODO: Create configuration file at /etc/rancher/k3s/config.yaml
Expand All @@ -48,9 +57,15 @@ func Up(options ...Option) error {
// TODO: Store state on server nodes to allow for configuration diffing later on.
// TODO: Fetch state from Git history.

// Disconnect from all nodes.
// Clean up and disconnect from all nodes.
for _, node := range nodes {
node.Disconnect()
if err := eng.Cleanup(node); err != nil {
return err
}

if err := node.Disconnect(); err != nil {
return err
}
}

return nil
Expand Down
7 changes: 1 addition & 6 deletions pkg/sshx/options.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package sshx

import (
"os"
"time"

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

// Options contains the configuration for an operation.
Expand All @@ -32,10 +30,7 @@ func (o *Options) Apply(options ...Option) (*Options, error) {
// GetDefaultOptions returns the default options
// for all operations of this library.
func GetDefaultOptions() *Options {
logger := log.Output(zerolog.ConsoleWriter{
Out: os.Stderr,
TimeFormat: time.RFC3339,
})
logger := zerolog.Nop()

return &Options{
Proxy: nil,
Expand Down

0 comments on commit e1612dd

Please sign in to comment.