Skip to content

Commit dca7478

Browse files
committed
CLID-686: Test to check that we fail gracefully when failing to retrieve release signature
1 parent d31e7f4 commit dca7478

2 files changed

Lines changed: 114 additions & 2 deletions

File tree

tests/integration/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ require (
1212
github.com/operator-framework/operator-registry v1.50.0
1313
github.com/sirupsen/logrus v1.9.4
1414
gopkg.in/yaml.v3 v3.0.1
15+
k8s.io/api v0.32.0
16+
sigs.k8s.io/yaml v1.4.0
1517
)
1618

1719
require (
@@ -168,7 +170,6 @@ require (
168170
gopkg.in/inf.v0 v0.9.1 // indirect
169171
gopkg.in/warnings.v0 v0.1.2 // indirect
170172
gopkg.in/yaml.v2 v2.4.0 // indirect
171-
k8s.io/api v0.32.0 // indirect
172173
k8s.io/apiextensions-apiserver v0.32.0 // indirect
173174
k8s.io/apimachinery v0.32.0 // indirect
174175
k8s.io/apiserver v0.32.0 // indirect
@@ -181,5 +182,4 @@ require (
181182
sigs.k8s.io/controller-runtime v0.19.4 // indirect
182183
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
183184
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
184-
sigs.k8s.io/yaml v1.4.0 // indirect
185185
)

tests/integration/signature_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
package integration_test
22

33
import (
4+
"encoding/json"
5+
"os"
46
"path/filepath"
7+
"strings"
58

69
. "github.com/onsi/ginkgo/v2"
10+
. "github.com/onsi/gomega"
11+
corev1 "k8s.io/api/core/v1"
12+
"sigs.k8s.io/yaml"
13+
14+
"github.com/openshift/oc-mirror/tests/integration/pkg/ocmirror"
715
)
816

917
var _ = Describe("signatures", func() {
@@ -48,6 +56,9 @@ var _ = Describe("signatures", func() {
4856
By("verifying signatures are present in the local registry")
4957
expectSignaturesInRegistry(*testRegistry)
5058

59+
By("verifying the signature configmap was generated correctly")
60+
expectSignatureConfigMapGenerated(workDir)
61+
5162
By("running delete with --delete-signatures")
5263
result, err = runner.DeletePhaseOne(ctx, filepath.Join(iscDir, discSignatures), workDir, "", testRegistry.Endpoint(),
5364
"--delete-signatures")
@@ -86,4 +97,105 @@ var _ = Describe("signatures", func() {
8697
By("verifying signature tags are still present")
8798
expectOnlySignatureTagsRemain(*testRegistry)
8899
})
100+
101+
It("fails gracefully when it fails to retrieve the release signature", func() {
102+
// Use a plain, unseeded working directory so no cached signature is found,
103+
// forcing oc-mirror to fetch it from OCP_SIGNATURE_URL.
104+
unseededWorkDir, err := os.MkdirTemp("", "oc-mirror-test-*")
105+
Expect(err).NotTo(HaveOccurred())
106+
defer cleanupWorkDir(unseededWorkDir)
107+
108+
By("running mirrorToDisk with an unreachable signature server")
109+
failingSigRunner := ocmirror.NewRunner(os.Getenv("OC_MIRROR_BINARY")).
110+
WithEnv([]string{"OCP_SIGNATURE_URL=http://127.0.0.1:1/"})
111+
result, err := failingSigRunner.MirrorToDisk(ctx, filepath.Join(iscDir, iscSignatures), unseededWorkDir)
112+
113+
By("verifying oc-mirror failed gracefully instead of panicking")
114+
expectOcMirrorExitCode(result, err, 2, "collection error", "http request")
115+
expectNoTarArchive(unseededWorkDir)
116+
})
117+
118+
Describe("release signature configmap", func() {
119+
It("should not generate a signature configmap when --ignore-release-signature is used", func() {
120+
// Use a plain, unseeded working directory to guarantee no signature is ever
121+
// cached, regardless of --ignore-release-signature.
122+
unseededWorkDir, err := os.MkdirTemp("", "oc-mirror-test-*")
123+
Expect(err).NotTo(HaveOccurred())
124+
defer cleanupWorkDir(unseededWorkDir)
125+
126+
By("running mirrorToDisk with --ignore-release-signature")
127+
result, err := runner.MirrorToDisk(ctx, filepath.Join(iscDir, iscSignatures), unseededWorkDir, "--ignore-release-signature")
128+
expectOcMirrorCommandSuccess(result, err)
129+
130+
By("running diskToMirror with --ignore-release-signature")
131+
result, err = runner.DiskToMirror(ctx, filepath.Join(iscDir, iscSignatures), unseededWorkDir, testRegistry.Endpoint(),
132+
"--ignore-release-signature", "--dest-tls-verify=false")
133+
expectOcMirrorCommandSuccess(result, err)
134+
135+
By("verifying no signature configmap was generated since no signature was ever cached")
136+
expectNoSignatureConfigMap(unseededWorkDir)
137+
})
138+
})
89139
})
140+
141+
// expectSignatureConfigMapGenerated verifies that the release signature configmap
142+
// (both JSON and YAML) was generated in working-dir/cluster-resources with the
143+
// expected static name, and that its binaryData matches the cached signature files
144+
// in working-dir/signatures byte-for-byte.
145+
func expectSignatureConfigMapGenerated(workDir string) {
146+
crDir := filepath.Join(workDir, dirWorkingDir, dirClusterResources)
147+
148+
var jsonCM corev1.ConfigMap
149+
jsonData, err := os.ReadFile(filepath.Join(crDir, "signature-configmap.json"))
150+
Expect(err).NotTo(HaveOccurred(), "signature-configmap.json not found")
151+
Expect(json.Unmarshal(jsonData, &jsonCM)).To(Succeed(), "failed to unmarshal signature-configmap.json")
152+
153+
var yamlCM corev1.ConfigMap
154+
yamlData, err := os.ReadFile(filepath.Join(crDir, "signature-configmap.yaml"))
155+
Expect(err).NotTo(HaveOccurred(), "signature-configmap.yaml not found")
156+
Expect(yaml.Unmarshal(yamlData, &yamlCM)).To(Succeed(), "failed to unmarshal signature-configmap.yaml")
157+
158+
for _, cm := range []corev1.ConfigMap{jsonCM, yamlCM} {
159+
Expect(cm.Name).To(Equal("mirrored-release-signatures"))
160+
Expect(cm.BinaryData).NotTo(BeEmpty())
161+
for key := range cm.BinaryData {
162+
Expect(key).To(MatchRegexp(`^sha256-[0-9a-f]{64}-\d+$`), "unexpected binaryData key format: %s", key)
163+
}
164+
}
165+
Expect(jsonCM.BinaryData).To(Equal(yamlCM.BinaryData), "json and yaml signature configmaps disagree on binaryData")
166+
167+
sigDir := filepath.Join(workDir, dirWorkingDir, "signatures")
168+
entries, err := os.ReadDir(sigDir)
169+
Expect(err).NotTo(HaveOccurred())
170+
Expect(entries).NotTo(BeEmpty(), "no cached signature files found in %s", sigDir)
171+
172+
for _, f := range entries {
173+
parts := strings.SplitN(f.Name(), "-sha256-", 2)
174+
Expect(parts).To(HaveLen(2), "unexpected signature file name: %s", f.Name())
175+
digest := parts[1]
176+
177+
data, err := os.ReadFile(filepath.Join(sigDir, f.Name()))
178+
Expect(err).NotTo(HaveOccurred())
179+
180+
found := false
181+
for key, val := range jsonCM.BinaryData {
182+
if strings.Contains(key, digest) {
183+
Expect(val).To(Equal(data), "binaryData content mismatch for key %s", key)
184+
found = true
185+
break
186+
}
187+
}
188+
Expect(found).To(BeTrue(), "no binaryData entry found for signature file %s", f.Name())
189+
}
190+
}
191+
192+
// expectNoSignatureConfigMap verifies that no release signature configmap was generated.
193+
func expectNoSignatureConfigMap(workDir string) {
194+
crDir := filepath.Join(workDir, dirWorkingDir, dirClusterResources)
195+
196+
_, errJSON := os.Stat(filepath.Join(crDir, "signature-configmap.json"))
197+
Expect(os.IsNotExist(errJSON)).To(BeTrue(), "expected signature-configmap.json to not exist")
198+
199+
_, errYAML := os.Stat(filepath.Join(crDir, "signature-configmap.yaml"))
200+
Expect(os.IsNotExist(errYAML)).To(BeTrue(), "expected signature-configmap.yaml to not exist")
201+
}

0 commit comments

Comments
 (0)