Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1fd95f7
microshift admin backup
pmtk May 11, 2023
c505f6b
configurable backup dest dir
pmtk May 18, 2023
da262e5
use config var for default value
pmtk May 18, 2023
3332008
more logs and logic for backup
pmtk May 20, 2023
3fa1bd7
ensure microshift is not running
pmtk May 20, 2023
c69fe38
move backup under data subcommand
pmtk May 22, 2023
f3cd8ca
DataManager interface
pmtk May 22, 2023
52fe5d3
check if svc is inactive instead of `ps aux`
pmtk May 22, 2023
59b7c7b
fix ireturn
pmtk May 22, 2023
8548161
rename `--dest` and make sure args are not empty
pmtk May 24, 2023
6fa81a2
rename DataManager to Manager
pmtk May 25, 2023
d8a68cb
catch empty args early
pmtk May 26, 2023
8d86dc3
log dir creation
pmtk May 26, 2023
35a428a
move logic around...
pmtk May 26, 2023
3d45018
rename microshiftShouldNotRun
pmtk May 26, 2023
b566524
rename existing backup instead of deleting it before having new one i…
pmtk May 26, 2023
58f172b
move BackupCfg validation to separate func
pmtk May 26, 2023
28fb007
tweak logs
pmtk May 26, 2023
41d41d2
tweak logic re errs in BackupConfig.Validate()
pmtk May 26, 2023
e90d88a
change backup unit of work start log
pmtk May 26, 2023
aced3e6
move microshift running check
pmtk May 26, 2023
25dd11b
--force to overwrite backup via cli
pmtk May 29, 2023
4bb597f
rename manager.go for better logs
pmtk May 29, 2023
b5d84fe
interface impl assertion and better 'Restore not impl' log
pmtk May 29, 2023
aeb0b2e
fix linter
pmtk May 31, 2023
5816743
separate std out and err
pmtk May 31, 2023
a6e672c
simplify by requiring non-existing backup name
pmtk May 31, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/microshift/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ func newCommand() *cobra.Command {
cmd.AddCommand(cmds.NewRunMicroshiftCommand())
cmd.AddCommand(cmds.NewVersionCommand(ioStreams))
cmd.AddCommand(cmds.NewShowConfigCommand(ioStreams))
cmd.AddCommand(cmds.NewAdminCommand())
return cmd
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/openshift/microshift

go 1.19
go 1.20

require (
github.com/apparentlymart/go-cidr v1.1.0
Expand Down
105 changes: 105 additions & 0 deletions pkg/admin/data/data_manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package data

import (
"bytes"
"fmt"
"os/exec"
"path/filepath"
"strings"

"github.com/openshift/microshift/pkg/config"
"github.com/openshift/microshift/pkg/util"
"k8s.io/klog/v2"
)

var (
cpArgs = []string{
"--verbose",
"--recursive",
"--preserve",
"--reflink=auto",
}
)

func NewManager(storage StoragePath) (*manager, error) {
if storage == "" {
return nil, &EmptyArgErr{argName: "storage"}
}
return &manager{storage: storage}, nil
}

var _ Manager = (*manager)(nil)

type manager struct {
storage StoragePath
}

func (dm *manager) GetBackupPath(name BackupName) string {
return filepath.Join(string(dm.storage), string(name))
}

func (dm *manager) BackupExists(name BackupName) (bool, error) {
return pathExists(dm.GetBackupPath(name))
}

func (dm *manager) Backup(name BackupName) error {
klog.InfoS("Backing up the data",
"storage", dm.storage, "name", name, "data", config.DataDir)

if name == "" {
return &EmptyArgErr{"name"}
}

if found, err := pathExists(string(dm.storage)); err != nil {
return err
} else if !found {
if makeDirErr := util.MakeDir(string(dm.storage)); makeDirErr != nil {
return fmt.Errorf("making %s directory failed: %w", dm.storage, makeDirErr)
}
klog.InfoS("Backup storage directory created", "path", dm.storage)
} else {
klog.InfoS("Backup storage directory already existed", "path", dm.storage)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This indicates an attempt to write over an existing backup, right? I would expect that to be an error.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, that's the "parent directory" where backups are stored. Maybe you have how can we name it better ("backup storage") or maybe just simply delete this log (and keep only one about creating /var/lib/microshift-backups/)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see what's going on now.

}

dest := dm.GetBackupPath(name)

if err := copyDataDir(dest); err != nil {
return err
}

klog.InfoS("Backup finished", "backup", dest, "data", config.DataDir)
return nil
}

func (dm *manager) Restore(n BackupName) error {
return fmt.Errorf("Restore not implemented")
}

func copyDataDir(dest string) error {
cmd := exec.Command("cp", append(cpArgs, config.DataDir, dest)...) //nolint:gosec
klog.InfoS("Executing command", "cmd", cmd)

var outb, errb bytes.Buffer
cmd.Stdout = &outb
cmd.Stderr = &errb
err := cmd.Run()

klog.InfoS("Command finished running", "cmd", cmd,
"stdout", strings.ReplaceAll(outb.String(), "\n", `, `),
"stderr", errb.String())

if err != nil {
return fmt.Errorf("command %s failed: %w", cmd, err)
}

klog.InfoS("Command successful", "cmd", cmd)
return nil
}

func pathExists(path string) (bool, error) {
exists, err := util.PathExists(path)
if err != nil {
return false, fmt.Errorf("checking if %s exists failed: %w", path, err)
}
return exists, nil
}
36 changes: 36 additions & 0 deletions pkg/admin/data/run_check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package data

import (
"fmt"
"os/exec"
"strings"

"k8s.io/klog/v2"
)

const (
expectedState = "inactive"
)

var (
services = []string{"microshift.service", "microshift-etcd.scope"}
)

func MicroShiftIsNotRunning() error {
for _, service := range services {
cmd := exec.Command("systemctl", "show", "-p", "ActiveState", "--value", service)
out, err := cmd.CombinedOutput()
state := strings.TrimSpace(string(out))
if err != nil {
return fmt.Errorf("error when checking if %s is active: %w", service, err)
}

klog.InfoS("Service state", "service", service, "state", state)

if state != expectedState {
return fmt.Errorf("service %s is %s - expected to be %s", service, state, expectedState)
}
}

return nil
}
24 changes: 24 additions & 0 deletions pkg/admin/data/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package data

import (
"fmt"
)

type EmptyArgErr struct {
argName string
}

func (e *EmptyArgErr) Error() string {
return fmt.Sprintf("empty argument: %s", e.argName)
}

type StoragePath string
type BackupName string

type Manager interface {
Backup(BackupName) error
Restore(BackupName) error

BackupExists(BackupName) (bool, error)
GetBackupPath(BackupName) string
}
75 changes: 75 additions & 0 deletions pkg/cmd/admin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package cmd

import (
"fmt"
"time"

"github.com/openshift/microshift/pkg/admin/data"
"github.com/openshift/microshift/pkg/config"
"github.com/openshift/microshift/pkg/version"

"github.com/spf13/cobra"
)

func backup(cmd *cobra.Command, args []string) error {
storage := data.StoragePath(cmd.Flag("storage").Value.String())
name := data.BackupName(cmd.Flag("name").Value.String())

dataManager, err := data.NewManager(storage)
if err != nil {
return err
}

if exists, err := dataManager.BackupExists(name); err != nil {
return err
} else if exists {
return fmt.Errorf("backup %s already exists", dataManager.GetBackupPath(name))
}

return dataManager.Backup(name)
}

func newAdminDataCommand() *cobra.Command {
backup := &cobra.Command{
Use: "backup",
Short: "Backup MicroShift data",
RunE: backup,
}

data := &cobra.Command{
Use: "data",
Short: "Commands for managing MicroShift data",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if cmd.Flag("storage").Value.String() == "" {
return fmt.Errorf("--storage must not be empty")
}

if cmd.Flag("name").Value.String() == "" {
return fmt.Errorf("--name must not be empty")
}

if err := data.MicroShiftIsNotRunning(); err != nil {
return fmt.Errorf("microshift must not be running: %w", err)
}

return nil
},
}
v := version.Get()
data.PersistentFlags().String("storage", config.BackupsDir, "Directory with backups")
data.PersistentFlags().String("name",
fmt.Sprintf("%s.%s__%s", v.Major, v.Minor, time.Now().UTC().Format("20060102_150405")),
"Backup name")

data.AddCommand(backup)
return data
}

func NewAdminCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "admin",
Short: "Commands for managing MicroShift",
}
cmd.AddCommand(newAdminDataCommand())
return cmd
}
2 changes: 1 addition & 1 deletion pkg/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func RunMicroshift(cfg *config.Config) error {
klog.Fatal(err)
}

if err := os.MkdirAll(config.DataDir, 0700); err != nil {
if err := util.MakeDir(config.DataDir); err != nil {
return fmt.Errorf("failed to create dir %q: %w", config.DataDir, err)
}

Expand Down
1 change: 1 addition & 0 deletions pkg/config/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
const (
ConfigFile = "/etc/microshift/config.yaml"
DataDir = "/var/lib/microshift"
BackupsDir = "/var/lib/microshift-backups"
)

func parse(contents []byte) (*Config, error) {
Expand Down
16 changes: 16 additions & 0 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package util

import (
"errors"
"fmt"
"os"
)

func Must(err error) {
Expand All @@ -16,3 +18,17 @@ func Default(s string, defaultS string) string {
}
return s
}

func PathExists(path string) (bool, error) {
if _, err := os.Stat(path); err == nil {
return true, nil
} else if errors.Is(err, os.ErrNotExist) {
return false, nil
} else {
return false, err
}
}

func MakeDir(path string) error {
return os.MkdirAll(path, 0700)
}