Skip to content

Commit bc37a91

Browse files
committed
import github.com/databacker/api instead of defining locally
Signed-off-by: Avi Deitcher <[email protected]>
1 parent e44221e commit bc37a91

35 files changed

+957
-963
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
uses: actions/checkout@v4
6060
- uses: actions/setup-go@v5
6161
with:
62-
go-version: '1.21'
62+
go-version: '1.22'
6363
- name: golangci-lint
6464
uses: golangci/golangci-lint-action@v6
6565
with:

.github/workflows/release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: Set up Go
2626
uses: actions/setup-go@v5
2727
with:
28-
go-version: 1.21
28+
go-version: 1.22
2929
- name: Build for all platforms
3030
run: |
3131
make build-all

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# mysql backup image
2-
FROM golang:1.21.13-alpine3.20 AS build
2+
FROM golang:1.22.9-alpine3.20 AS build
33

44
COPY . /src/mysql-backup
55
WORKDIR /src/mysql-backup

cmd/common_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"context"
45
"reflect"
56

67
"github.com/databacker/mysql-backup/pkg/core"
@@ -19,17 +20,17 @@ func newMockExecs() *mockExecs {
1920
return m
2021
}
2122

22-
func (m *mockExecs) Dump(opts core.DumpOptions) (core.DumpResults, error) {
23+
func (m *mockExecs) Dump(ctx context.Context, opts core.DumpOptions) (core.DumpResults, error) {
2324
args := m.Called(opts)
2425
return core.DumpResults{}, args.Error(0)
2526
}
2627

27-
func (m *mockExecs) Restore(opts core.RestoreOptions) error {
28+
func (m *mockExecs) Restore(ctx context.Context, opts core.RestoreOptions) error {
2829
args := m.Called(opts)
2930
return args.Error(0)
3031
}
3132

32-
func (m *mockExecs) Prune(opts core.PruneOptions) error {
33+
func (m *mockExecs) Prune(ctx context.Context, opts core.PruneOptions) error {
3334
args := m.Called(opts)
3435
return args.Error(0)
3536
}

cmd/dump.go

Lines changed: 137 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
package cmd
22

33
import (
4+
"context"
45
"fmt"
56
"strings"
67

78
"github.com/google/uuid"
89
"github.com/spf13/cobra"
910
"github.com/spf13/viper"
11+
"go.opentelemetry.io/otel/codes"
1012

13+
"github.com/databacker/api/go/api"
1114
"github.com/databacker/mysql-backup/pkg/compression"
1215
"github.com/databacker/mysql-backup/pkg/core"
1316
"github.com/databacker/mysql-backup/pkg/storage"
17+
"github.com/databacker/mysql-backup/pkg/util"
1418
)
1519

1620
const (
@@ -38,92 +42,84 @@ func dumpCmd(passedExecs execs, cmdConfig *cmdConfiguration) (*cobra.Command, er
3842
bindFlags(cmd, v)
3943
},
4044
RunE: func(cmd *cobra.Command, args []string) error {
45+
ctx := context.Background()
46+
// this is the tracer that we will use throughout the entire run
47+
tracer := getTracer("dump")
48+
ctx = util.ContextWithTracer(ctx, tracer)
49+
_, startupSpan := tracer.Start(ctx, "startup")
4150
cmdConfig.logger.Debug("starting dump")
51+
defer func() {
52+
tp := getTracerProvider()
53+
tp.ForceFlush(ctx)
54+
_ = tp.Shutdown(ctx)
55+
}()
4256
// check targets
4357
targetURLs := v.GetStringSlice("target")
4458
var (
45-
targets []storage.Storage
46-
err error
59+
dumpConfig *api.Dump
60+
scriptsConfig *api.Scripts
4761
)
48-
if len(targetURLs) > 0 {
49-
for _, t := range targetURLs {
50-
store, err := storage.ParseURL(t, cmdConfig.creds)
51-
if err != nil {
52-
return fmt.Errorf("invalid target url: %v", err)
53-
}
54-
targets = append(targets, store)
55-
}
56-
} else {
57-
// try the config file
58-
if cmdConfig.configuration != nil {
59-
// parse the target objects, then the ones listed for the backup
60-
targetStructures := cmdConfig.configuration.Targets
61-
dumpTargets := cmdConfig.configuration.Dump.Targets
62-
for _, t := range dumpTargets {
63-
var store storage.Storage
64-
if target, ok := targetStructures[t]; !ok {
65-
return fmt.Errorf("target %s from dump configuration not found in targets configuration", t)
66-
} else {
67-
store, err = target.Storage.Storage()
68-
if err != nil {
69-
return fmt.Errorf("target %s from dump configuration has invalid URL: %v", t, err)
70-
}
71-
}
72-
targets = append(targets, store)
73-
}
62+
if cmdConfig.configuration != nil {
63+
dumpConfig = cmdConfig.configuration.Dump
64+
if dumpConfig != nil {
65+
scriptsConfig = dumpConfig.Scripts
7466
}
7567
}
68+
targets, err := parseTargets(targetURLs, cmdConfig)
69+
if err != nil {
70+
return fmt.Errorf("error parsing targets: %v", err)
71+
}
7672
if len(targets) == 0 {
7773
return fmt.Errorf("no targets specified")
7874
}
7975
safechars := v.GetBool("safechars")
80-
if !v.IsSet("safechars") && cmdConfig.configuration != nil {
81-
safechars = cmdConfig.configuration.Dump.Safechars
76+
if !v.IsSet("safechars") && dumpConfig != nil && dumpConfig.Safechars != nil {
77+
safechars = *dumpConfig.Safechars
8278
}
8379
include := v.GetStringSlice("include")
84-
if len(include) == 0 && cmdConfig.configuration != nil {
85-
include = cmdConfig.configuration.Dump.Include
80+
if len(include) == 0 && dumpConfig != nil && dumpConfig.Include != nil {
81+
include = *dumpConfig.Include
8682
}
8783
// make this slice nil if it's empty, so it is consistent; used mainly for test consistency
8884
if len(include) == 0 {
8985
include = nil
9086
}
9187
exclude := v.GetStringSlice("exclude")
92-
if len(exclude) == 0 && cmdConfig.configuration != nil {
93-
exclude = cmdConfig.configuration.Dump.Exclude
88+
if len(exclude) == 0 && dumpConfig != nil && dumpConfig.Exclude != nil {
89+
exclude = *dumpConfig.Exclude
9490
}
9591
// make this slice nil if it's empty, so it is consistent; used mainly for test consistency
9692
if len(exclude) == 0 {
9793
exclude = nil
9894
}
9995
preBackupScripts := v.GetString("pre-backup-scripts")
100-
if preBackupScripts == "" && cmdConfig.configuration != nil {
101-
preBackupScripts = cmdConfig.configuration.Dump.Scripts.PreBackup
96+
if preBackupScripts == "" && scriptsConfig != nil && scriptsConfig.PreBackup != nil {
97+
preBackupScripts = *scriptsConfig.PreBackup
10298
}
10399
postBackupScripts := v.GetString("post-backup-scripts")
104-
if postBackupScripts == "" && cmdConfig.configuration != nil {
105-
postBackupScripts = cmdConfig.configuration.Dump.Scripts.PostBackup
100+
if postBackupScripts == "" && scriptsConfig != nil && scriptsConfig.PostBackup != nil {
101+
postBackupScripts = *scriptsConfig.PostBackup
106102
}
107103
noDatabaseName := v.GetBool("no-database-name")
108-
if !v.IsSet("no-database-name") && cmdConfig.configuration != nil {
109-
noDatabaseName = cmdConfig.configuration.Dump.NoDatabaseName
104+
if !v.IsSet("no-database-name") && dumpConfig != nil && dumpConfig.NoDatabaseName != nil {
105+
noDatabaseName = *dumpConfig.NoDatabaseName
110106
}
111107
compact := v.GetBool("compact")
112-
if !v.IsSet("compact") && cmdConfig.configuration != nil {
113-
compact = cmdConfig.configuration.Dump.Compact
108+
if !v.IsSet("compact") && dumpConfig != nil && dumpConfig.Compact != nil {
109+
compact = *dumpConfig.Compact
114110
}
115111
maxAllowedPacket := v.GetInt("max-allowed-packet")
116-
if !v.IsSet("max-allowed-packet") && cmdConfig.configuration != nil && cmdConfig.configuration.Dump.MaxAllowedPacket != 0 {
117-
maxAllowedPacket = cmdConfig.configuration.Dump.MaxAllowedPacket
112+
if !v.IsSet("max-allowed-packet") && dumpConfig != nil && dumpConfig.MaxAllowedPacket != nil && *dumpConfig.MaxAllowedPacket != 0 {
113+
maxAllowedPacket = *dumpConfig.MaxAllowedPacket
118114
}
119115

120116
// compression algorithm: check config, then CLI/env var overrides
121117
var (
122118
compressionAlgo string
123119
compressor compression.Compressor
124120
)
125-
if cmdConfig.configuration != nil {
126-
compressionAlgo = cmdConfig.configuration.Dump.Compression
121+
if cmdConfig.configuration != nil && dumpConfig.Compression != nil {
122+
compressionAlgo = *dumpConfig.Compression
127123
}
128124
compressionVar := v.GetString("compression")
129125
if compressionVar != "" {
@@ -138,41 +134,21 @@ func dumpCmd(passedExecs execs, cmdConfig *cmdConfiguration) (*cobra.Command, er
138134

139135
// retention, if enabled
140136
retention := v.GetString("retention")
141-
if retention == "" && cmdConfig.configuration != nil {
142-
retention = cmdConfig.configuration.Prune.Retention
137+
if retention == "" && cmdConfig.configuration != nil && cmdConfig.configuration.Prune.Retention != nil {
138+
retention = *cmdConfig.configuration.Prune.Retention
143139
}
144140
filenamePattern := v.GetString("filename-pattern")
145141

146-
if !v.IsSet("filename-pattern") && cmdConfig.configuration != nil {
147-
filenamePattern = cmdConfig.configuration.Dump.FilenamePattern
142+
if !v.IsSet("filename-pattern") && dumpConfig != nil && dumpConfig.FilenamePattern != nil {
143+
filenamePattern = *dumpConfig.FilenamePattern
148144
}
149145
if filenamePattern == "" {
150146
filenamePattern = defaultFilenamePattern
151147
}
152148

153149
// timer options
154-
once := v.GetBool("once")
155-
if !v.IsSet("once") && cmdConfig.configuration != nil {
156-
once = cmdConfig.configuration.Dump.Schedule.Once
157-
}
158-
cron := v.GetString("cron")
159-
if cron == "" && cmdConfig.configuration != nil {
160-
cron = cmdConfig.configuration.Dump.Schedule.Cron
161-
}
162-
begin := v.GetString("begin")
163-
if begin == "" && cmdConfig.configuration != nil {
164-
begin = cmdConfig.configuration.Dump.Schedule.Begin
165-
}
166-
frequency := v.GetInt("frequency")
167-
if frequency == 0 && cmdConfig.configuration != nil {
168-
frequency = cmdConfig.configuration.Dump.Schedule.Frequency
169-
}
170-
timerOpts := core.TimerOptions{
171-
Once: once,
172-
Cron: cron,
173-
Begin: begin,
174-
Frequency: frequency,
175-
}
150+
timerOpts := parseTimerOptions(v, cmdConfig.configuration)
151+
176152
var executor execs
177153
executor = &core.Executor{}
178154
if passedExecs != nil {
@@ -182,7 +158,14 @@ func dumpCmd(passedExecs execs, cmdConfig *cmdConfiguration) (*cobra.Command, er
182158

183159
// at this point, any errors should not have usage
184160
cmd.SilenceUsage = true
161+
162+
// done with the startup
163+
startupSpan.End()
164+
185165
if err := executor.Timer(timerOpts, func() error {
166+
// start a new span for the dump, should not be a child of the startup one
167+
tracerCtx, dumpSpan := tracer.Start(ctx, "run")
168+
defer dumpSpan.End()
186169
uid := uuid.New()
187170
dumpOpts := core.DumpOptions{
188171
Targets: targets,
@@ -199,15 +182,18 @@ func dumpCmd(passedExecs execs, cmdConfig *cmdConfiguration) (*cobra.Command, er
199182
Run: uid,
200183
FilenamePattern: filenamePattern,
201184
}
202-
_, err := executor.Dump(dumpOpts)
185+
_, err := executor.Dump(tracerCtx, dumpOpts)
203186
if err != nil {
187+
dumpSpan.SetStatus(codes.Error, fmt.Sprintf("error running dump: %v", err))
204188
return fmt.Errorf("error running dump: %w", err)
205189
}
206190
if retention != "" {
207-
if err := executor.Prune(core.PruneOptions{Targets: targets, Retention: retention}); err != nil {
191+
if err := executor.Prune(tracerCtx, core.PruneOptions{Targets: targets, Retention: retention}); err != nil {
192+
dumpSpan.SetStatus(codes.Error, fmt.Sprintf("error running prune: %v", err))
208193
return fmt.Errorf("error running prune: %w", err)
209194
}
210195
}
196+
dumpSpan.SetStatus(codes.Ok, "dump complete")
211197
return nil
212198
}); err != nil {
213199
return fmt.Errorf("error running command: %w", err)
@@ -278,3 +264,80 @@ S3: If it is a URL of the format s3://bucketname/path then it will connect via S
278264

279265
return cmd, nil
280266
}
267+
268+
func parseTimerOptions(v *viper.Viper, config *api.ConfigSpec) core.TimerOptions {
269+
var scheduleConfig *api.Schedule
270+
if config != nil {
271+
dumpConfig := config.Dump
272+
if dumpConfig != nil {
273+
scheduleConfig = dumpConfig.Schedule
274+
}
275+
}
276+
once := v.GetBool("once")
277+
if !v.IsSet("once") && scheduleConfig != nil && scheduleConfig.Once != nil {
278+
once = *scheduleConfig.Once
279+
}
280+
cron := v.GetString("cron")
281+
if cron == "" && scheduleConfig != nil && scheduleConfig.Cron != nil {
282+
cron = *scheduleConfig.Cron
283+
}
284+
begin := v.GetString("begin")
285+
if begin == "" && scheduleConfig != nil && scheduleConfig.Begin != nil {
286+
begin = fmt.Sprintf("%d", *scheduleConfig.Begin)
287+
}
288+
frequency := v.GetInt("frequency")
289+
if frequency == 0 && scheduleConfig != nil && scheduleConfig.Frequency != nil {
290+
frequency = *scheduleConfig.Frequency
291+
}
292+
return core.TimerOptions{
293+
Once: once,
294+
Cron: cron,
295+
Begin: begin,
296+
Frequency: frequency,
297+
}
298+
299+
}
300+
301+
func parseTargets(urls []string, cmdConfig *cmdConfiguration) ([]storage.Storage, error) {
302+
var targets []storage.Storage
303+
if len(urls) > 0 {
304+
for _, t := range urls {
305+
store, err := storage.ParseURL(t, cmdConfig.creds)
306+
if err != nil {
307+
return nil, fmt.Errorf("invalid target url: %v", err)
308+
}
309+
targets = append(targets, store)
310+
}
311+
} else {
312+
// try the config file
313+
if cmdConfig.configuration != nil {
314+
// parse the target objects, then the ones listed for the backup
315+
var (
316+
targetStructures map[string]api.Target
317+
dumpTargets []string
318+
)
319+
if cmdConfig.configuration.Targets != nil {
320+
targetStructures = *cmdConfig.configuration.Targets
321+
}
322+
if cmdConfig.configuration != nil && cmdConfig.configuration.Dump != nil && cmdConfig.configuration.Dump.Targets != nil {
323+
dumpTargets = *cmdConfig.configuration.Dump.Targets
324+
}
325+
for _, t := range dumpTargets {
326+
var (
327+
store storage.Storage
328+
err error
329+
)
330+
if target, ok := targetStructures[t]; !ok {
331+
return nil, fmt.Errorf("target %s from dump configuration not found in targets configuration", t)
332+
} else {
333+
store, err = storage.FromTarget(target)
334+
if err != nil {
335+
return nil, fmt.Errorf("target %s from dump configuration has invalid URL: %v", t, err)
336+
}
337+
}
338+
targets = append(targets, store)
339+
}
340+
}
341+
}
342+
return targets, nil
343+
}

0 commit comments

Comments
 (0)