Skip to content
This repository was archived by the owner on Jun 14, 2023. It is now read-only.

Commit 86f793b

Browse files
authored
Merge pull request #42 from flanksource/issue-41
feat: find and update resource based on the object key
2 parents 07e1198 + a972a37 commit 86f793b

10 files changed

Lines changed: 125 additions & 94 deletions

File tree

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ jobs:
44
test:
55
strategy:
66
matrix:
7-
go-version: [1.13.x]
7+
go-version: [1.14.x]
88
platform: [ubuntu-latest]
99
k8s:
10-
- v1.16.9
10+
- v1.20.7
1111
runs-on: ${{ matrix.platform }}
1212
steps:
1313
- name: Install Go

api/v1/gitopsapi_types.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ type GitopsAPISpec struct {
5757
Kustomization string `json:"kustomization,omitempty"`
5858

5959
// The path to save the resource into, should including templating to make it unique per cluster/namespace/kind/name tuple e.g. `specs/clusters/{{.cluster}}/{{.name}}.yaml`
60-
// +required
6160
Path string `json:"path,omitempty"`
61+
// SearchPath defines the subdir in which the matching object needs to be searched. In case Path and SearchPath both are defined SearchPath takes precedence
62+
SearchPath string `json:"searchPath,omitempty"`
6263
}
6364

6465
type PullRequestTemplate struct {

config/crd/bases/git.flanksource.com_gitopsapis.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ spec:
8686
items:
8787
type: string
8888
type: array
89+
searchPath:
90+
description: SearchPath defines the subdir in which the matching object
91+
needs to be searched. In case Path and SearchPath both are defined
92+
SearchPath takes precedence
93+
type: string
8994
secretRef:
9095
description: The secret name containing the Git credentials. For SSH
9196
repositories the secret must contain SSH_PRIVATE_KEY, SSH_PRIVATE_KEY_PASSORD

config/deploy/crd.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,11 @@ spec:
337337
items:
338338
type: string
339339
type: array
340+
searchPath:
341+
description: SearchPath defines the subdir in which the matching object
342+
needs to be searched. In case Path and SearchPath both are defined
343+
SearchPath takes precedence
344+
type: string
340345
secretRef:
341346
description: The secret name containing the Git credentials. For SSH
342347
repositories the secret must contain SSH_PRIVATE_KEY, SSH_PRIVATE_KEY_PASSORD

config/deploy/operator.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,11 @@ spec:
337337
items:
338338
type: string
339339
type: array
340+
searchPath:
341+
description: SearchPath defines the subdir in which the matching object
342+
needs to be searched. In case Path and SearchPath both are defined
343+
SearchPath takes precedence
344+
type: string
340345
secretRef:
341346
description: The secret name containing the Git credentials. For SSH
342347
repositories the secret must contain SSH_PRIVATE_KEY, SSH_PRIVATE_KEY_PASSORD

controllers/gitopsapi_controller.go

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ import (
2323
"io"
2424
"io/ioutil"
2525
"net/http"
26+
"os"
2627
"path"
28+
"path/filepath"
2729
"strings"
2830
"time"
2931

@@ -141,6 +143,8 @@ func HandleGitopsAPI(ctx context.Context, logger logr.Logger, git connectors.Con
141143
if err = json.Unmarshal(body, &obj.Object); err != nil {
142144
return hash, pr, errors.WithStack(err)
143145
}
146+
objKey := fmt.Sprintf("%s-%s-%s", obj.GetName(), obj.GetNamespace(), obj.GetKind())
147+
contentPath := fmt.Sprintf("%s-%s-%s.yaml", obj.GetKind(), obj.GetNamespace(), obj.GetName())
144148
api.Spec.Branch, err = text.Template(api.Spec.Branch, obj.Object)
145149
if err != nil {
146150
return
@@ -149,11 +153,47 @@ func HandleGitopsAPI(ctx context.Context, logger logr.Logger, git connectors.Con
149153
if err != nil {
150154
return
151155
}
152-
153-
if api.Spec.Path == "" {
154-
api.Spec.Path = fmt.Sprintf("%s-%s-%s.yaml", obj.GetKind(), obj.GetNamespace(), obj.GetName())
156+
if api.Spec.SearchPath != "" {
157+
repoRoot := fs.Root()
158+
if strings.HasSuffix(repoRoot, "/") {
159+
api.Spec.SearchPath = repoRoot + api.Spec.SearchPath
160+
} else {
161+
api.Spec.SearchPath = repoRoot + "/" + api.Spec.SearchPath
162+
}
163+
if err := filepath.Walk(api.Spec.SearchPath, func(filePath string, info os.FileInfo, err error) error {
164+
if err != nil {
165+
return err
166+
}
167+
if info.Name() == "kustomization.yaml" || info.IsDir() {
168+
return nil
169+
}
170+
if path.Ext(filePath) == ".yaml" || path.Ext(filePath) == ".yml" {
171+
resource := unstructured.Unstructured{Object: make(map[string]interface{})}
172+
buf, err := ioutil.ReadFile(filePath)
173+
if err != nil {
174+
return err
175+
}
176+
if err := yaml.Unmarshal(buf, &resource); err != nil {
177+
return err
178+
}
179+
resourceKey := fmt.Sprintf("%s-%s-%s", resource.GetName(), resource.GetNamespace(), resource.GetKind())
180+
if objKey == resourceKey {
181+
contentPath, err = filepath.Rel(repoRoot, filePath)
182+
if err != nil {
183+
return err
184+
}
185+
return nil
186+
}
187+
}
188+
return nil
189+
}); err != nil {
190+
return hash, pr, errors.WithStack(err)
191+
}
192+
} else {
193+
if api.Spec.Path != "" {
194+
contentPath = api.Spec.Path
195+
}
155196
}
156-
157197
body, err = yaml.Marshal(obj.Object)
158198
if err != nil {
159199
return
@@ -165,14 +205,11 @@ func HandleGitopsAPI(ctx context.Context, logger logr.Logger, git connectors.Con
165205
if err != nil {
166206
return
167207
}
168-
169-
contentPath, err := text.Template(api.Spec.Path, obj.Object)
208+
contentPath, err = text.Template(contentPath, obj.Object)
170209
if err != nil {
171210
return
172211
}
173-
174212
logger.Info("Saving to", "path", contentPath, "kustomization", kustomizationPath, "object", title)
175-
176213
if err = copy(body, contentPath, fs, work); err != nil {
177214
return
178215
}

test/config.yaml

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
name: kind-kind
2-
patches:
3-
- ./test/patch1.yaml
42
domain: 127.0.0.1.nip.io
53
dex:
64
disabled: true
@@ -20,25 +18,13 @@ podSubnet: 100.200.0.0/16
2018
serviceSubnet: 100.100.0.0/16
2119
calico:
2220
version: v3.8.2
23-
s3:
24-
endpoint: http://minio.minio.svc:9000
25-
externalEndpoint: minio.127.0.0.1.nip.io
26-
bucket: harbor
27-
access_key: minio
28-
secret_key: minio123
29-
region: us-east1
30-
kmsMasterKey: minio-demo-key:6368616e676520746869732070617373776f726420746f206120736563726574
31-
usePathStyle: true
32-
skipTLSVerify: true
33-
e2e:
34-
minio: true
3521
ca:
36-
cert: .certs/root-ca.crt
37-
privateKey: .certs/root-ca.key
22+
cert: ../.certs/root-ca.crt
23+
privateKey: ../.certs/root-ca.key
3824
password: foobar
3925
ingressCA:
40-
cert: .certs/ingress-ca.crt
41-
privateKey: .certs/ingress-ca.key
26+
cert: ../.certs/ingress-ca.crt
27+
privateKey: ../.certs/ingress-ca.key
4228
password: foobar
4329
test:
4430
exclude:

test/e2e.go

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ var (
4646
k8s *kubernetes.Clientset
4747
crdK8s crdclient.Client
4848
tests = map[string]Test{
49-
"git-operator-is-running": TestGitOperatorIsRunning,
50-
"github-branch-sync": TestGithubBranchSync,
51-
"github-pr-github-sync": TestGithubPRSync,
52-
"github-pr-crd-sync": TestGithubPRCRDSync,
53-
"github-gitops-api": TestGitopsAPI,
49+
"git-operator-is-running": TestGitOperatorIsRunning,
50+
"github-branch-sync": TestGithubBranchSync,
51+
"github-pr-github-sync": TestGithubPRSync,
52+
"github-pr-crd-sync": TestGithubPRCRDSync,
53+
"github-gitops-api": TestGitopsAPI,
54+
"github-gitops-api-search-path": TestGitopsAPISearchPath,
5455
}
5556
scheme = runtime.NewScheme()
5657
log = ctrl.Log.WithName("e2e")
@@ -85,7 +86,7 @@ func main() {
8586
os.Exit(1)
8687
}
8788

88-
timeout = flag.Duration("timeout", 10*time.Minute, "Global timeout for all tests")
89+
timeout = flag.Duration("timeout", 15*time.Minute, "Global timeout for all tests")
8990
flag.Parse()
9091

9192
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
@@ -181,6 +182,50 @@ func TestGitopsAPI(ctx context.Context, test *console.TestResults) error {
181182
return err
182183
}
183184

185+
func TestGitopsAPISearchPath(ctx context.Context, test *console.TestResults) error {
186+
git, err := connectors.NewConnector(ctx, crdK8s, k8s, log, "platform-system", "https://github.com/"+repository, &v1.LocalObjectReference{
187+
Name: "github",
188+
})
189+
if err != nil {
190+
return err
191+
}
192+
branchName := getBranchName("test")
193+
body := `
194+
{
195+
"apiVersion": "v1",
196+
"data": {
197+
"some-key": "some-value",
198+
"new-key": "new-value"
199+
},
200+
"kind": "ConfigMap",
201+
"metadata": {
202+
"name": "test-configmap",
203+
"namespace": "default"
204+
}
205+
}
206+
`
207+
208+
log.Info("json", "value", body)
209+
_, pr, err := controllers.HandleGitopsAPI(ctx, log, git, gitv1.GitopsAPI{
210+
Spec: gitv1.GitopsAPISpec{
211+
GitRepository: repository,
212+
Branch: branchName,
213+
SearchPath: "resources/",
214+
PullRequest: &gitv1.PullRequestTemplate{
215+
Title: "New Automated PR - {{.metadata.name}}",
216+
Body: "Somebody created a new PR {{.metadata.name}}",
217+
},
218+
},
219+
}, bytes.NewReader([]byte(body)))
220+
221+
if pr != 0 {
222+
if err := git.ClosePullRequest(ctx, pr); err != nil {
223+
return err
224+
}
225+
}
226+
return err
227+
}
228+
184229
func TestGitOperatorIsRunning(ctx context.Context, test *console.TestResults) error {
185230
pods, err := k8s.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{LabelSelector: "control-plane=git-operator"})
186231
if err != nil {
@@ -206,7 +251,7 @@ func TestGithubBranchSync(ctx context.Context, test *console.TestResults) error
206251
}
207252
test.Passf("TestGithubBranchSync", "Successfully created branch %s", branchName)
208253

209-
gitBranchGetCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Minute)
254+
gitBranchGetCtx, cancelFunc := context.WithTimeout(ctx, 3*time.Minute)
210255
defer cancelFunc()
211256
crdName := fmt.Sprintf("gitrepository-sample-%s", branchName)
212257
gitBranch, err := waitForGitBranch(gitBranchGetCtx, crdName)
@@ -268,7 +313,7 @@ func TestGithubPRSync(ctx context.Context, test *console.TestResults) error {
268313
return err
269314
}
270315

271-
gitPRGetCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Minute)
316+
gitPRGetCtx, cancelFunc := context.WithTimeout(ctx, 3*time.Minute)
272317
defer cancelFunc()
273318
crdName := fmt.Sprintf("gitrepository-sample-%d", *pr.Number)
274319
gitPR, err := waitForGitPullRequest(gitPRGetCtx, crdName)
@@ -363,7 +408,7 @@ func TestGithubPRCRDSync(ctx context.Context, test *console.TestResults) error {
363408
return err
364409
}
365410

366-
gitPRGetCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Minute)
411+
gitPRGetCtx, cancelFunc := context.WithTimeout(ctx, 3*time.Minute)
367412
defer cancelFunc()
368413
gitPR, err := waitForGitPullRequestFromCrd(gitPRGetCtx, branchName)
369414
if err != nil {

test/e2e.sh

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
set -e
44

5-
export KARINA_VERSION=v0.16.2
5+
export KARINA_VERSION=v0.50.1
66
export KARINA="./karina -c test/config.yaml"
77
export KUBECONFIG=~/.kube/config
88
export DOCKER_API_VERSION=1.39
@@ -30,14 +30,9 @@ export PATH=$(pwd)/.bin:$PATH
3030

3131
$KARINA ca generate --name root-ca --cert-path .certs/root-ca.crt --private-key-path .certs/root-ca.key --password foobar --expiry 1
3232
$KARINA ca generate --name ingress-ca --cert-path .certs/ingress-ca.crt --private-key-path .certs/ingress-ca.key --password foobar --expiry 1
33-
$KARINA provision kind-cluster
34-
35-
$KARINA deploy calico
36-
kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true
3733

38-
$KARINA deploy base
39-
$KARINA deploy stubs
40-
kubectl create namespace platform-system
34+
$KARINA provision kind-cluster
35+
$KARINA deploy phases --bootstrap --stubs
4136

4237
export IMG=flanksource/git-operator:v1
4338
make docker-build

test/patch1.yaml

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)