Skip to content

Commit b758aab

Browse files
authored
Add migrate and prune cmd (#208)
* Add migrate cmd Signed-off-by: Md. Ishtiaq Islam <[email protected]> * Add prune cmd Signed-off-by: Md. Ishtiaq Islam <[email protected]> * Refactor Signed-off-by: Md. Ishtiaq Islam <[email protected]> * Resolve comments Signed-off-by: Md. Ishtiaq Islam <[email protected]> --------- Signed-off-by: Md. Ishtiaq Islam <[email protected]>
1 parent cad2245 commit b758aab

File tree

7 files changed

+426
-32
lines changed

7 files changed

+426
-32
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ ARCH := $(if $(GOARCH),$(GOARCH),$(shell go env GOARCH))
5656
GO_VERSION ?= 1.23
5757
BUILD_IMAGE ?= ghcr.io/appscode/golang-dev:$(GO_VERSION)
5858

59-
RESTIC_VER := 0.13.1
59+
RESTIC_VER := 0.17.3
6060

6161
OUTBIN = bin/$(BIN)-$(OS)-$(ARCH)
6262
ifeq ($(OS),windows)
@@ -220,7 +220,7 @@ lint: $(BUILD_DIRS)
220220
--env GO111MODULE=on \
221221
--env GOFLAGS="-mod=vendor" \
222222
$(BUILD_IMAGE) \
223-
golangci-lint run --enable $(ADDTL_LINTERS) --timeout=10m --skip-files="generated.*\.go$\" --skip-dirs-use-default
223+
golangci-lint run --enable $(ADDTL_LINTERS) --timeout=10m --exclude-files="generated.*\.go$\" --exclude-dirs-use-default
224224

225225
$(BUILD_DIRS):
226226
@mkdir -p $@

pkg/cli.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const (
3535
passwordFile = "password.txt"
3636

3737
ResticEnvs = "restic-envs"
38-
ResticRegistry = "stashed"
38+
ResticRegistry = "restic"
3939
ResticImage = "restic"
4040
ResticTag = "latest"
4141
cmdKubectl = "kubectl"

pkg/migrate.go

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the AppsCode Community License 1.0.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package pkg
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"os"
23+
"path/filepath"
24+
25+
"stash.appscode.dev/apimachinery/apis/stash/v1alpha1"
26+
cs "stash.appscode.dev/apimachinery/client/clientset/versioned"
27+
"stash.appscode.dev/apimachinery/pkg/restic"
28+
"stash.appscode.dev/stash/pkg/util"
29+
30+
"github.com/pkg/errors"
31+
"github.com/spf13/cobra"
32+
core "k8s.io/api/core/v1"
33+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34+
"k8s.io/cli-runtime/pkg/genericclioptions"
35+
"k8s.io/client-go/kubernetes"
36+
"k8s.io/client-go/rest"
37+
"k8s.io/klog/v2"
38+
)
39+
40+
type migrateOptions struct {
41+
kubeClient *kubernetes.Clientset
42+
config *rest.Config
43+
repo *v1alpha1.Repository
44+
}
45+
46+
func NewCmdMigrateRepositoryToV2(clientGetter genericclioptions.RESTClientGetter) *cobra.Command {
47+
opt := migrateOptions{}
48+
49+
cmd := &cobra.Command{
50+
Use: "migrate",
51+
Short: `Migrate restic repository to v2`,
52+
DisableAutoGenTag: true,
53+
RunE: func(cmd *cobra.Command, args []string) error {
54+
if len(args) == 0 || args[0] == "" {
55+
return fmt.Errorf("repository name not found")
56+
}
57+
repositoryName := args[0]
58+
59+
var err error
60+
opt.config, err = clientGetter.ToRESTConfig()
61+
if err != nil {
62+
return errors.Wrap(err, "failed to read kubeconfig")
63+
}
64+
namespace, _, err = clientGetter.ToRawKubeConfigLoader().Namespace()
65+
if err != nil {
66+
return err
67+
}
68+
69+
stshclient, err := cs.NewForConfig(opt.config)
70+
if err != nil {
71+
return err
72+
}
73+
74+
opt.repo, err = stshclient.StashV1alpha1().Repositories(namespace).Get(context.TODO(), repositoryName, metav1.GetOptions{})
75+
if err != nil {
76+
return err
77+
}
78+
79+
opt.kubeClient, err = kubernetes.NewForConfig(opt.config)
80+
if err != nil {
81+
return err
82+
}
83+
84+
if opt.repo.Spec.Backend.Local != nil {
85+
// get the pod that mount this repository as volume
86+
pod, err := getBackendMountingPod(opt.kubeClient, opt.repo)
87+
if err != nil {
88+
return err
89+
}
90+
return opt.migrateRepoFromPod(pod)
91+
}
92+
93+
return opt.migrateRepo()
94+
},
95+
}
96+
97+
cmd.Flags().StringVar(&imgRestic.Registry, "docker-registry", imgRestic.Registry, "Docker image registry for restic cli")
98+
cmd.Flags().StringVar(&imgRestic.Tag, "image-tag", imgRestic.Tag, "Restic docker image tag")
99+
100+
return cmd
101+
}
102+
103+
func (opt *migrateOptions) migrateRepoFromPod(pod *core.Pod) error {
104+
if err := opt.executeMigrateRepoCmdInPod(pod); err != nil {
105+
return err
106+
}
107+
108+
klog.Infof("Repository %s/%s upgraded to version 2", namespace, opt.repo.Name)
109+
return nil
110+
}
111+
112+
func (opt *migrateOptions) executeMigrateRepoCmdInPod(pod *core.Pod) error {
113+
command := []string{"/stash-enterprise", "migrate"}
114+
command = append(command, "--repo-name", opt.repo.Name, "--repo-namespace", opt.repo.Namespace)
115+
116+
out, err := execCommandOnPod(opt.kubeClient, opt.config, pod, command)
117+
if string(out) != "" {
118+
klog.Infoln("Output:", string(out))
119+
}
120+
return err
121+
}
122+
123+
func (opt *migrateOptions) migrateRepo() error {
124+
// get source repository secret
125+
secret, err := opt.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), opt.repo.Spec.Backend.StorageSecretName, metav1.GetOptions{})
126+
if err != nil {
127+
return err
128+
}
129+
130+
if err = os.MkdirAll(ScratchDir, 0o755); err != nil {
131+
return err
132+
}
133+
defer os.RemoveAll(ScratchDir)
134+
135+
// configure restic wrapper
136+
extraOpt := util.ExtraOptions{
137+
StorageSecret: secret,
138+
ScratchDir: ScratchDir,
139+
}
140+
// configure setupOption
141+
setupOpt, err := util.SetupOptionsForRepository(*opt.repo, extraOpt)
142+
if err != nil {
143+
return fmt.Errorf("setup option for repository failed")
144+
}
145+
146+
resticWrapper, err := restic.NewResticWrapper(setupOpt)
147+
if err != nil {
148+
return err
149+
}
150+
151+
localDirs := &cliLocalDirectories{
152+
configDir: filepath.Join(ScratchDir, configDirName),
153+
}
154+
// dump restic's environments into `restic-env` file.
155+
// we will pass this env file to restic docker container.
156+
err = resticWrapper.DumpEnv(localDirs.configDir, ResticEnvs)
157+
if err != nil {
158+
return err
159+
}
160+
161+
extraAgrs := []string{
162+
"upgrade_repo_v2", "--no-cache",
163+
}
164+
165+
// For TLS secured Minio/REST server, specify cert path
166+
if resticWrapper.GetCaPath() != "" {
167+
extraAgrs = append(extraAgrs, "--cacert", resticWrapper.GetCaPath())
168+
}
169+
170+
if err = runCmdViaDocker(*localDirs, "migrate", extraAgrs); err != nil {
171+
return err
172+
}
173+
klog.Infof("Repository %s/%s upgraded to version 2", namespace, opt.repo.Name)
174+
return nil
175+
}

0 commit comments

Comments
 (0)