Skip to content

Commit 91e71d2

Browse files
authored
fix: update flux apply and tests to ensure updates fail if broken (#169)
<!-- markdownlint-disable MD041 --> #### What this PR does / why we need it #### Which issue(s) this PR fixes <!-- Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> --------- Signed-off-by: Gergely Brautigam <[email protected]>
1 parent 68b793d commit 91e71d2

File tree

6 files changed

+538
-1
lines changed

6 files changed

+538
-1
lines changed

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v5
18+
with:
19+
go-version: '1.24.2'
20+
21+
- name: Cache Go modules
22+
uses: actions/cache@v4
23+
with:
24+
path: |
25+
~/.cache/go-build
26+
~/go/pkg/mod
27+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
28+
restore-keys: |
29+
${{ runner.os }}-go-
30+
31+
- name: Run tests
32+
run: make test-unit

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ vet: ## Run go vet against code.
3434
test: ## Run all of the tests
3535
go test ./...
3636

37+
.PHONY: test-unit
38+
test-unit: ## Run unit tests only
39+
go test ./internal/... -short
40+

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
github.com/open-component-model/git-controller v0.12.1
2525
github.com/open-component-model/ocm-controller v0.26.5
2626
github.com/open-component-model/replication-controller v0.13.1
27+
github.com/stretchr/testify v1.10.0
2728
k8s.io/api v0.33.3
2829
k8s.io/apiextensions-apiserver v0.33.3
2930
k8s.io/apimachinery v0.33.3
@@ -269,6 +270,7 @@ require (
269270
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
270271
github.com/pjbgf/sha1cd v0.3.2 // indirect
271272
github.com/pkg/errors v0.9.1 // indirect
273+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
272274
github.com/prometheus/client_golang v1.22.0 // indirect
273275
github.com/prometheus/client_model v0.6.2 // indirect
274276
github.com/prometheus/common v0.65.0 // indirect

internal/utils/flux_apply.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"time"
2727

2828
"github.com/fluxcd/cli-utils/pkg/kstatus/polling"
29+
"github.com/fluxcd/pkg/ssa/normalize"
2930
"github.com/fluxcd/pkg/ssa/utils"
3031
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3132
"k8s.io/cli-runtime/pkg/genericclioptions"
@@ -49,7 +50,7 @@ func Apply(ctx context.Context, rcg genericclioptions.RESTClientGetter, opts *ru
4950
return "", fmt.Errorf("no Kubernetes objects found at: %s", manifestPath)
5051
}
5152

52-
if err := ssa.SetNativeKindsDefaults(objs); err != nil {
53+
if err := normalize.UnstructuredList(objs); err != nil {
5354
return "", err
5455
}
5556

internal/utils/flux_apply_test.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
Copyright 2021 The Flux authors
3+
4+
Licensed under the Apache License, Version 2.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+
http://www.apache.org/licenses/LICENSE-2.0
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 utils
18+
19+
import (
20+
"os"
21+
"path/filepath"
22+
"testing"
23+
24+
"github.com/stretchr/testify/assert"
25+
"github.com/stretchr/testify/require"
26+
)
27+
28+
func TestIsRecognizedKustomizationFile(t *testing.T) {
29+
tests := []struct {
30+
name string
31+
path string
32+
expected bool
33+
}{
34+
{
35+
name: "kustomization.yaml",
36+
path: "/path/to/kustomization.yaml",
37+
expected: true,
38+
},
39+
{
40+
name: "kustomization.yml",
41+
path: "/path/to/kustomization.yml",
42+
expected: true,
43+
},
44+
{
45+
name: "Kustomization",
46+
path: "/path/to/Kustomization",
47+
expected: true,
48+
},
49+
{
50+
name: "regular yaml file",
51+
path: "/path/to/deployment.yaml",
52+
expected: false,
53+
},
54+
{
55+
name: "no extension",
56+
path: "/path/to/somefile",
57+
expected: false,
58+
},
59+
}
60+
61+
for _, tt := range tests {
62+
t.Run(tt.name, func(t *testing.T) {
63+
result := isRecognizedKustomizationFile(tt.path)
64+
assert.Equal(t, tt.expected, result)
65+
})
66+
}
67+
}
68+
69+
func TestReadObjects(t *testing.T) {
70+
tests := []struct {
71+
name string
72+
setupFile func(t *testing.T) (root, manifestPath string)
73+
expectError bool
74+
}{
75+
{
76+
name: "valid yaml file",
77+
setupFile: func(t *testing.T) (string, string) {
78+
dir := t.TempDir()
79+
manifestPath := filepath.Join(dir, "test.yaml")
80+
content := `apiVersion: v1
81+
kind: ConfigMap
82+
metadata:
83+
name: test-cm
84+
namespace: default
85+
data:
86+
key: value`
87+
require.NoError(t, os.WriteFile(manifestPath, []byte(content), 0644))
88+
return dir, manifestPath
89+
},
90+
expectError: false,
91+
},
92+
{
93+
name: "directory instead of file",
94+
setupFile: func(t *testing.T) (string, string) {
95+
dir := t.TempDir()
96+
subDir := filepath.Join(dir, "subdir")
97+
require.NoError(t, os.Mkdir(subDir, 0755))
98+
return dir, subDir
99+
},
100+
expectError: true,
101+
},
102+
{
103+
name: "non-existent file",
104+
setupFile: func(t *testing.T) (string, string) {
105+
dir := t.TempDir()
106+
return dir, filepath.Join(dir, "missing.yaml")
107+
},
108+
expectError: true,
109+
},
110+
{
111+
name: "kustomization file",
112+
setupFile: func(t *testing.T) (string, string) {
113+
dir := t.TempDir()
114+
kustomizationPath := filepath.Join(dir, "kustomization.yaml")
115+
content := `apiVersion: kustomize.config.k8s.io/v1beta1
116+
kind: Kustomization
117+
resources:
118+
- deployment.yaml`
119+
require.NoError(t, os.WriteFile(kustomizationPath, []byte(content), 0644))
120+
121+
deploymentPath := filepath.Join(dir, "deployment.yaml")
122+
deploymentContent := `apiVersion: apps/v1
123+
kind: Deployment
124+
metadata:
125+
name: test-deployment`
126+
require.NoError(t, os.WriteFile(deploymentPath, []byte(deploymentContent), 0644))
127+
return dir, kustomizationPath
128+
},
129+
expectError: false,
130+
},
131+
}
132+
133+
for _, tt := range tests {
134+
t.Run(tt.name, func(t *testing.T) {
135+
root, manifestPath := tt.setupFile(t)
136+
137+
objects, err := readObjects(root, manifestPath)
138+
139+
if tt.expectError {
140+
require.Error(t, err)
141+
assert.Nil(t, objects)
142+
} else {
143+
require.NoError(t, err)
144+
assert.NotEmpty(t, objects)
145+
}
146+
})
147+
}
148+
}

0 commit comments

Comments
 (0)