Skip to content

Commit 103434d

Browse files
author
Emruz Hossain
committed
Refactor code
Signed-off-by: Emruz Hossain <emruz@appscode.com>
1 parent ad144f2 commit 103434d

File tree

257 files changed

+12604
-7294
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

257 files changed

+12604
-7294
lines changed

go.mod

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,19 @@ require (
66
github.com/spf13/cobra v1.2.1
77
go.bytebuilders.dev/license-verifier/kubernetes v0.9.7
88
gomodules.xyz/flags v0.1.3
9-
gomodules.xyz/go-sh v0.1.0
109
gomodules.xyz/logs v0.0.6
1110
gomodules.xyz/sets v0.2.1
1211
gomodules.xyz/x v0.0.13
1312
k8s.io/api v0.21.1
1413
k8s.io/apimachinery v0.21.1
1514
k8s.io/client-go v0.21.1
1615
k8s.io/klog/v2 v2.9.0
17-
kmodules.xyz/client-go v0.0.0-20220308080632-2543b61b64fd
18-
kmodules.xyz/custom-resources v0.0.0-20220317043135-5c76c52c975d
19-
kmodules.xyz/offshoot-api v0.0.0-20220317044008-01567138fc2f
20-
sigs.k8s.io/yaml v1.2.0
21-
stash.appscode.dev/apimachinery v0.18.1-0.20220321055929-ee132c17707b
22-
stash.appscode.dev/elasticsearch v0.0.0-20220317210913-fc6cd8252e2a
16+
kmodules.xyz/client-go v0.0.0-20220317213815-2a6d5a5784f2
17+
kmodules.xyz/custom-resources v0.0.0-20220317220154-7beb809b1f5e
18+
kmodules.xyz/offshoot-api v0.0.0-20220329041708-c076b2bcb0f8
19+
sigs.k8s.io/yaml v1.3.0
20+
stash.appscode.dev/apimachinery v0.19.1-0.20220407092220-1fb00845d1f7
21+
stash.appscode.dev/elasticsearch v0.0.0-20220329183444-6b505bc9eb9f
2322
)
2423

2524
replace bitbucket.org/ww/goautoneg => gomodules.xyz/goautoneg v0.0.0-20120707110453-a547fc61f48d

go.sum

Lines changed: 60 additions & 42 deletions
Large diffs are not rendered by default.

pkg/manager/application.go

Lines changed: 75 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,22 @@ package manager
22

33
import (
44
"context"
5-
kerr "k8s.io/apimachinery/pkg/api/errors"
5+
"path/filepath"
6+
7+
"stash.appscode.dev/apimachinery/apis/stash/v1beta1"
8+
"stash.appscode.dev/manifest-backup/pkg/sanitizers"
9+
610
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
711
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
812
"k8s.io/apimachinery/pkg/runtime/schema"
9-
"k8s.io/apimachinery/pkg/runtime/serializer"
1013
"k8s.io/apimachinery/pkg/types"
1114
"k8s.io/client-go/discovery"
1215
"k8s.io/client-go/dynamic"
13-
"k8s.io/client-go/kubernetes/scheme"
1416
"k8s.io/client-go/rest"
1517
"k8s.io/client-go/restmapper"
16-
"path/filepath"
17-
"stash.appscode.dev/apimachinery/apis/stash/v1beta1"
18-
"stash.appscode.dev/manifest-backup/pkg/manager/sanitizers"
1918
)
2019

2120
type applicationBackupManager struct {
22-
disc discovery.DiscoveryInterface
2321
di dynamic.Interface
2422
namespace string
2523
storage Writer
@@ -45,175 +43,129 @@ func newApplicationBackupManager(opt BackupOptions) BackupManager {
4543
}
4644

4745
func (opt applicationBackupManager) Dump() error {
48-
var err error
49-
opt.config.QPS = 1e6
50-
opt.config.Burst = 1e6
51-
if err := rest.SetKubernetesDefaults(opt.config); err != nil {
52-
return err
53-
}
54-
opt.config.NegotiatedSerializer = serializer.WithoutConversionCodecFactory{CodecFactory: scheme.Codecs}
55-
if opt.config.UserAgent == "" {
56-
opt.config.UserAgent = rest.DefaultKubernetesUserAgent()
57-
}
58-
59-
opt.disc, err = discovery.NewDiscoveryClientForConfig(opt.config)
60-
if err != nil {
61-
return err
62-
}
63-
64-
opt.di, err = dynamic.NewForConfig(opt.config)
65-
if err != nil {
66-
return err
67-
}
68-
69-
gv, err := schema.ParseGroupVersion(opt.target.APIVersion)
70-
if err != nil {
71-
return err
72-
}
73-
gvk := gv.WithKind(opt.target.Kind)
74-
75-
apiResources, err := restmapper.GetAPIGroupResources(opt.disc)
46+
gvr, err := opt.getRootObjectGVR()
7647
if err != nil {
77-
return err
48+
return nil
7849
}
79-
mapper := restmapper.NewDiscoveryRESTMapper(apiResources)
80-
mapping, err := mapper.RESTMapping(schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version)
50+
rootObj, err := opt.getRootObject(*gvr)
8151
if err != nil {
8252
return err
8353
}
84-
ri := opt.di.Resource(mapping.Resource).Namespace(opt.namespace)
8554

86-
rootObj, err := ri.Get(context.TODO(), opt.target.Name, metav1.GetOptions{})
87-
if err != nil {
88-
return err
55+
rTree := treeBuilder{
56+
resourceTree: make(map[types.UID][]resourceRef),
8957
}
90-
91-
resourceTree := make(map[types.UID][]resourceRef)
9258
rootUID := types.UID("root")
93-
resourceTree[rootUID] = []resourceRef{
59+
rTree.resourceTree[rootUID] = []resourceRef{
9460
{
95-
gvr: mapping.Resource,
61+
gvr: *gvr,
9662
name: rootObj.GetName(),
9763
namespace: rootObj.GetNamespace(),
64+
kind: rootObj.GetKind(),
9865
},
9966
}
10067

10168
if opt.includeDependants {
102-
err := opt.generateDependencyTree(resourceTree)
69+
err := opt.generateDependencyTree(&rTree)
10370
if err != nil {
10471
return err
10572
}
10673
}
107-
return opt.dumpResourceTree(resourceTree, rootUID)
74+
return opt.dumpResourceTree(rTree.resourceTree, rootUID, opt.dataDir)
10875
}
10976

110-
type resourceRef struct {
111-
gvr schema.GroupVersionResource
112-
name string
113-
namespace string
114-
}
77+
func (opt *applicationBackupManager) getRootObjectGVR() (*schema.GroupVersionResource, error) {
78+
disc, err := discovery.NewDiscoveryClientForConfig(opt.config)
79+
if err != nil {
80+
return nil, err
81+
}
82+
apiResources, err := restmapper.GetAPIGroupResources(disc)
83+
if err != nil {
84+
return nil, err
85+
}
11586

116-
func (opt *applicationBackupManager) generateDependencyTree(resourceTree map[types.UID][]resourceRef) error {
117-
resList, err := opt.disc.ServerPreferredResources()
87+
gv, err := schema.ParseGroupVersion(opt.target.APIVersion)
11888
if err != nil {
119-
return err
89+
return nil, err
12090
}
91+
gvk := gv.WithKind(opt.target.Kind)
12192

122-
for _, group := range resList {
123-
err := opt.traverseGroup(resourceTree, group)
124-
if err != nil {
125-
return err
126-
}
93+
mapper := restmapper.NewDiscoveryRESTMapper(apiResources)
94+
mapping, err := mapper.RESTMapping(schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version)
95+
if err != nil {
96+
return nil, err
12797
}
128-
return nil
98+
return &mapping.Resource, nil
12999
}
130100

131-
func (opt *applicationBackupManager) traverseGroup(resourceTree map[types.UID][]resourceRef, group *metav1.APIResourceList) error {
132-
gv, err := schema.ParseGroupVersion(group.GroupVersion)
101+
func (opt *applicationBackupManager) getRootObject(gvr schema.GroupVersionResource) (*unstructured.Unstructured, error) {
102+
var err error
103+
opt.di, err = dynamic.NewForConfig(opt.config)
133104
if err != nil {
134-
return err
105+
return nil, err
135106
}
107+
ri := opt.di.Resource(gvr).Namespace(opt.namespace)
108+
return ri.Get(context.TODO(), opt.target.Name, metav1.GetOptions{})
109+
}
136110

137-
for _, res := range group.APIResources {
138-
if isSubResource(res.Name) || !hasGetListVerbs(res.Verbs) {
139-
continue
140-
}
141-
// don't process non-namespaced resources when target is a namespace
142-
if !res.Namespaced && opt.namespace != "" {
143-
continue
144-
}
145-
146-
err := opt.traverseResourceInstances(resourceTree, gv.WithResource(res.Name))
147-
if err != nil {
148-
return err
149-
}
111+
func (opt *applicationBackupManager) generateDependencyTree(tb *treeBuilder) error {
112+
rp := resourceProcessor{
113+
config: opt.config,
114+
namespace: opt.namespace,
115+
selector: opt.selector,
116+
itemProcessor: tb,
150117
}
151-
return nil
118+
return rp.processAPIResources()
152119
}
153120

154-
func (opt *applicationBackupManager) traverseResourceInstances(resourceTree map[types.UID][]resourceRef, gvr schema.GroupVersionResource) error {
155-
var next string
156-
for {
157-
var ri dynamic.ResourceInterface
158-
if opt.namespace != "" {
159-
ri = opt.di.Resource(gvr).Namespace(opt.namespace)
160-
} else {
161-
ri = opt.di.Resource(gvr)
162-
}
163-
164-
resp, err := ri.List(context.TODO(), metav1.ListOptions{
165-
Limit: 250,
166-
Continue: next,
167-
LabelSelector: opt.selector,
168-
})
169-
if err != nil {
170-
if !kerr.IsNotFound(err) {
171-
return err
172-
}
173-
return nil
174-
}
175-
176-
opt.processItems(resourceTree, resp.Items, gvr)
121+
type resourceRef struct {
122+
gvr schema.GroupVersionResource
123+
name string
124+
namespace string
125+
kind string
126+
}
177127

178-
next = resp.GetContinue()
179-
if next == "" {
180-
break
181-
}
182-
}
183-
return nil
128+
type treeBuilder struct {
129+
resourceTree map[types.UID][]resourceRef
184130
}
185131

186-
func (opt *applicationBackupManager) processItems(resourceTree map[types.UID][]resourceRef, items []unstructured.Unstructured, gvr schema.GroupVersionResource) {
132+
func (opt treeBuilder) Process(items []unstructured.Unstructured, gvr schema.GroupVersionResource) error {
187133
for _, r := range items {
188134
ownerRefs := r.GetOwnerReferences()
189135
for i := range ownerRefs {
190-
if _, ok := resourceTree[ownerRefs[i].UID]; !ok {
191-
resourceTree[ownerRefs[i].UID] = make([]resourceRef, 0)
136+
if _, ok := opt.resourceTree[ownerRefs[i].UID]; !ok {
137+
opt.resourceTree[ownerRefs[i].UID] = make([]resourceRef, 0)
192138
}
193-
resourceTree[ownerRefs[i].UID] = append(resourceTree[ownerRefs[i].UID], resourceRef{
139+
opt.resourceTree[ownerRefs[i].UID] = append(opt.resourceTree[ownerRefs[i].UID], resourceRef{
194140
gvr: gvr,
195141
name: r.GetName(),
196142
namespace: r.GetNamespace(),
143+
kind: r.GetKind(),
197144
})
198145
}
199146
}
147+
return nil
200148
}
201149

202-
func (opt *applicationBackupManager) dumpResourceTree(resourceTree map[types.UID][]resourceRef, rootUID types.UID) error {
150+
func (opt *applicationBackupManager) dumpResourceTree(resourceTree map[types.UID][]resourceRef, rootUID types.UID, prefix string) error {
203151
for _, r := range resourceTree[rootUID] {
204-
childUID, err := opt.dumpItem(r)
152+
childUID, err := opt.dumpItem(r, prefix)
205153
if err != nil {
206154
return err
207155
}
208-
err = opt.dumpResourceTree(resourceTree, childUID)
156+
childPrefix := prefix
157+
if rootUID != "root" {
158+
childPrefix = filepath.Join(prefix, r.kind, r.name)
159+
}
160+
err = opt.dumpResourceTree(resourceTree, childUID, childPrefix)
209161
if err != nil {
210162
return err
211163
}
212164
}
213165
return nil
214166
}
215167

216-
func (opt *applicationBackupManager) dumpItem(r resourceRef) (types.UID, error) {
168+
func (opt *applicationBackupManager) dumpItem(r resourceRef, prefix string) (types.UID, error) {
217169
var ri dynamic.ResourceInterface
218170
if r.namespace != "" {
219171
ri = opt.di.Resource(r.gvr).Namespace(r.namespace)
@@ -237,16 +189,15 @@ func (opt *applicationBackupManager) dumpItem(r resourceRef) (types.UID, error)
237189
delete(data, "status")
238190
}
239191

240-
fileName := getFileName(obj, true, opt.dataDir)
192+
fileName := opt.getFileName(obj, prefix)
241193
return uid, storeItem(fileName, data, opt.storage)
242194
}
243195

244-
func getFileName(r *unstructured.Unstructured, isNamespaced bool, dataDir string) string {
245-
prefix := ""
246-
if isNamespaced {
247-
prefix = filepath.Join(dataDir, "namespaces", r.GetNamespace())
248-
} else {
249-
prefix = filepath.Join(dataDir, "global")
196+
func (opt *applicationBackupManager) getFileName(r *unstructured.Unstructured, prefix string) string {
197+
if opt.target.Kind == r.GetKind() &&
198+
opt.target.Name == r.GetName() &&
199+
opt.namespace == r.GetNamespace() {
200+
return filepath.Join(prefix, r.GetName()) + ".yaml"
250201
}
251-
return filepath.Join(prefix, r.GetKind(), r.GetName()) + ".yaml"
202+
return filepath.Join(prefix, r.GetKind(), r.GetName(), r.GetName()) + ".yaml"
252203
}

0 commit comments

Comments
 (0)