File: utils.go

package info (click to toggle)
golang-github-checkpoint-restore-checkpointctl 1.3.0%2Bds1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 628 kB
  • sloc: ansic: 208; makefile: 172; sh: 40
file content (135 lines) | stat: -rw-r--r-- 3,154 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package internal

import (
	"fmt"
	"io"
	"os"
	"strings"
	"text/tabwriter"
	"time"

	metadata "github.com/checkpoint-restore/checkpointctl/lib"
)

func FormatTime(microseconds uint32) string {
	if microseconds < 1000 {
		return fmt.Sprintf("%d µs", microseconds)
	}

	var value float64
	var unit string

	if microseconds < 1000000 {
		value = float64(microseconds) / 1000
		unit = "ms"
	} else {
		duration := time.Duration(microseconds) * time.Microsecond
		value = duration.Seconds()
		unit = "s"
	}

	// Trim trailing zeros and dot
	formatted := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.5g", value), "0"), ".")

	return fmt.Sprintf("%s %s", formatted, unit)
}

type Task struct {
	CheckpointFilePath string
	OutputDir          string
}

func CreateTasks(args []string, requiredFiles []string) ([]Task, error) {
	tasks := make([]Task, 0, len(args))

	for _, input := range args {
		tar, err := os.Stat(input)
		if err != nil {
			return nil, err
		}
		if !tar.Mode().IsRegular() {
			return nil, fmt.Errorf("input %s not a regular file", input)
		}

		// Check if there is a checkpoint directory in the archive file
		checkpointDirExists, err := isFileInArchive(input, metadata.CheckpointDirectory, true)
		if err != nil {
			return nil, err
		}

		if !checkpointDirExists {
			return nil, fmt.Errorf("checkpoint directory is missing in the archive file: %s", input)
		}

		dir, err := os.MkdirTemp("", "checkpointctl")
		if err != nil {
			return nil, err
		}

		if err := UntarFiles(input, dir, requiredFiles); err != nil {
			return nil, err
		}

		tasks = append(tasks, Task{CheckpointFilePath: input, OutputDir: dir})
	}

	return tasks, nil
}

// cleanupTasks removes all output directories of given tasks
func CleanupTasks(tasks []Task) {
	for _, task := range tasks {
		if err := os.RemoveAll(task.OutputDir); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
	}
}

// Constant values are based on kubectl's tabwriter settings:
// https://github.com/kubernetes/cli-runtime/blob/master/pkg/printers/tabwriter.go
const (
	tabwriterMinWidth = 6
	tabwriterWidth    = 4
	tabwriterPadding  = 3
	tabwriterPadChar  = ' '
	tabwriterFlags    = 0
)

// GetNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text.
func GetNewTabWriter(output io.Writer) *tabwriter.Writer {
	return tabwriter.NewWriter(output, tabwriterMinWidth, tabwriterWidth, tabwriterPadding, tabwriterPadChar, tabwriterFlags)
}

// WriteTableHeader writes the header row and separator line for a table
func WriteTableHeader(w *tabwriter.Writer, header []string) {
	// Print header
	for i, h := range header {
		if i > 0 {
			fmt.Fprint(w, "\t")
		}
		fmt.Fprint(w, strings.ToUpper(h))
	}
	fmt.Fprintln(w)

	// Print separator line
	for i := range header {
		if i > 0 {
			fmt.Fprint(w, "\t")
		}
		fmt.Fprint(w, strings.Repeat("-", len(header[i])))
	}
	fmt.Fprintln(w)
}

// WriteTableRows writes the data rows for a table
func WriteTableRows(w *tabwriter.Writer, rows [][]string) {
	for _, row := range rows {
		for i, cell := range row {
			if i > 0 {
				fmt.Fprint(w, "\t")
			}
			fmt.Fprint(w, cell)
		}
		fmt.Fprintln(w)
	}
}