Skip to content

Commit 9b0ebd2

Browse files
Merge pull request #29557 from stbenjam/local-binary
NO-JIRA: Allow overriding extension binary to local path
2 parents fb69a72 + 8285ecf commit 9b0ebd2

File tree

4 files changed

+139
-4
lines changed

4 files changed

+139
-4
lines changed

pkg/test/extensions/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ credentials to use are found in this code, and extensively documented in code
2828
comments. The following environment variables are available to force certain
2929
behaviors:
3030

31+
### Extension Binary
32+
33+
When developing locally, you may want to use a locally built extension
34+
binary. You can override the binary from the registry by setting:
35+
36+
```
37+
export EXTENSION_BINARY_OVERRIDE_HYPERKUBE="/home/sally/git/kubernetes/_output/bin/k8s-tests-ext"
38+
```
39+
40+
This overrides all extension binaries registered for that image tag
41+
(i.e. hyperkube). In the uncommon situation where an image tag is
42+
providing multiple test binaries, you can more specifically override one
43+
like this:
44+
45+
```
46+
export EXTENSION_BINARY_OVERRIDE_HYPERKUBE_USR_BIN_K8S_TESTS_EXT_GZ="/home/sally/git/kubernetes/_output/bin/k8s-tests-ext"
47+
```
48+
3149
### Caching
3250

3351
By default, binaries will be cached in `$XDG_CACHE_HOME/openshift-tests`

pkg/test/extensions/binary.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (b *TestBinary) Info(ctx context.Context) (*ExtensionInfo, error) {
7070
command := exec.Command(b.binaryPath, "info")
7171
infoJson, err := runWithTimeout(ctx, command, 10*time.Minute)
7272
if err != nil {
73-
return nil, fmt.Errorf("failed running '%s info': %w", b.binaryPath, err)
73+
return nil, fmt.Errorf("failed running '%s info': %w\nOutput: %s", b.binaryPath, err, infoJson)
7474
}
7575
jsonBegins := bytes.IndexByte(infoJson, '{')
7676
jsonEnds := bytes.LastIndexByte(infoJson, '}')
@@ -106,7 +106,7 @@ func (b *TestBinary) ListTests(ctx context.Context, envFlags EnvironmentFlags) (
106106
command.Args = append(command.Args, envFlags.ArgStrings()...)
107107
testList, err := runWithTimeout(ctx, command, 10*time.Minute)
108108
if err != nil {
109-
return nil, fmt.Errorf("failed running '%s list': %w", b.binaryPath, err)
109+
return nil, fmt.Errorf("failed running '%s list': %w\nOutput: %s", b.binaryPath, err, testList)
110110
}
111111
buf := bytes.NewBuffer(testList)
112112
for {
@@ -212,7 +212,7 @@ func (b *TestBinary) ListImages(ctx context.Context) (ImageSet, error) {
212212
command := exec.Command(b.binaryPath, "images")
213213
output, err := runWithTimeout(ctx, command, 10*time.Minute)
214214
if err != nil {
215-
return nil, fmt.Errorf("failed running '%s list': %w", b.binaryPath, err)
215+
return nil, fmt.Errorf("failed running '%s list': %w\nOutput: %s", b.binaryPath, err, output)
216216
}
217217

218218
var images []Image

pkg/test/extensions/provider.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package extensions
22

33
import (
44
"fmt"
5-
"github.com/sirupsen/logrus"
65
"os"
76
"path"
87
"path/filepath"
@@ -11,6 +10,7 @@ import (
1110

1211
imagev1 "github.com/openshift/api/image/v1"
1312
"github.com/pkg/errors"
13+
"github.com/sirupsen/logrus"
1414

1515
"github.com/openshift/origin/test/extended/util"
1616
)
@@ -98,6 +98,20 @@ func (provider *ExternalBinaryProvider) ExtractBinaryFromReleaseImage(tag, binar
9898
return nil, fmt.Errorf("extraction path is not set, cleanup was already run")
9999
}
100100

101+
// Allow overriding image path to an already existing local path, mostly useful
102+
// for development.
103+
if override := binaryPathOverride(tag, binary); override != "" {
104+
logrus.WithFields(logrus.Fields{
105+
"tag": tag,
106+
"binary": binary,
107+
"override": override,
108+
}).Info("Found override for this extension")
109+
return &TestBinary{
110+
imageTag: tag,
111+
binaryPath: override,
112+
}, nil
113+
}
114+
101115
// Resolve the image tag from the image stream.
102116
image := ""
103117
for _, t := range provider.imageStream.Spec.Tags {
@@ -187,3 +201,22 @@ func cleanOldCacheFiles(dir string) {
187201
}
188202
logrus.Infof("Cleaned up old cached data in %v", time.Since(start))
189203
}
204+
205+
func binaryPathOverride(imageTag, binaryPath string) string {
206+
safeEnvVar := strings.NewReplacer("/", "_", "-", "_", ".", "_")
207+
208+
// Check for a specific override for this binary path, less common but allows supporting
209+
// images that have multiple test binaries.
210+
// Example: EXTENSION_BINARY_OVERRIDE_HYPERKUBE_USR_BIN_K8S_TESTS_EXT_GZ
211+
specificOverrideEnvVar := fmt.Sprintf("EXTENSION_BINARY_OVERRIDE_%s_%s",
212+
strings.ToUpper(safeEnvVar.Replace(imageTag)),
213+
strings.ToUpper(safeEnvVar.Replace(strings.TrimPrefix(binaryPath, "/"))),
214+
)
215+
if specificOverride := os.Getenv(specificOverrideEnvVar); specificOverride != "" {
216+
return specificOverride
217+
}
218+
219+
// Check for a global override for all binaries in this image
220+
// Example: EXTENSION_BINARY_OVERRIDE_HYPERKUBE
221+
return os.Getenv(fmt.Sprintf("EXTENSION_BINARY_OVERRIDE_%s", strings.ToUpper(safeEnvVar.Replace(imageTag))))
222+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package extensions
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestBinaryPathOverride(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
imageTag string
14+
binaryPath string
15+
envVars map[string]string
16+
expectedPath string
17+
}{
18+
{
19+
name: "Global override for image",
20+
imageTag: "hyperkube",
21+
binaryPath: "/usr/bin/k8s-tests-ext",
22+
envVars: map[string]string{
23+
"EXTENSION_BINARY_OVERRIDE_HYPERKUBE": "/custom/global/path",
24+
},
25+
expectedPath: "/custom/global/path",
26+
},
27+
{
28+
name: "Specific override for binary",
29+
imageTag: "hyperkube",
30+
binaryPath: "/usr/bin/k8s-tests-ext",
31+
envVars: map[string]string{
32+
"EXTENSION_BINARY_OVERRIDE_HYPERKUBE_USR_BIN_K8S_TESTS_EXT": "/custom/specific/path",
33+
},
34+
expectedPath: "/custom/specific/path",
35+
},
36+
{
37+
name: "No overrides",
38+
imageTag: "hyperkube",
39+
binaryPath: "/usr/bin/k8s-tests-ext",
40+
envVars: map[string]string{},
41+
expectedPath: "",
42+
},
43+
{
44+
name: "Specific override takes precedence over global",
45+
imageTag: "hyperkube",
46+
binaryPath: "/usr/bin/k8s-tests-ext",
47+
envVars: map[string]string{
48+
"EXTENSION_BINARY_OVERRIDE_HYPERKUBE": "/custom/global/path",
49+
"EXTENSION_BINARY_OVERRIDE_HYPERKUBE_USR_BIN_K8S_TESTS_EXT": "/custom/specific/path",
50+
},
51+
expectedPath: "/custom/specific/path",
52+
},
53+
{
54+
name: "Special characters in image and binary path",
55+
imageTag: "special-image",
56+
binaryPath: "/usr/local/bin/special-tests-1.2.3",
57+
envVars: map[string]string{
58+
"EXTENSION_BINARY_OVERRIDE_SPECIAL_IMAGE_USR_LOCAL_BIN_SPECIAL_TESTS_1_2_3": "/custom/path/for-special",
59+
},
60+
expectedPath: "/custom/path/for-special",
61+
},
62+
}
63+
64+
for _, tt := range tests {
65+
t.Run(tt.name, func(t *testing.T) {
66+
for k, v := range tt.envVars {
67+
err := os.Setenv(k, v)
68+
assert.NoError(t, err)
69+
}
70+
71+
result := binaryPathOverride(tt.imageTag, tt.binaryPath)
72+
73+
if result != tt.expectedPath {
74+
t.Errorf("binaryPathOverride(%q, %q) = %q; want %q",
75+
tt.imageTag, tt.binaryPath, result, tt.expectedPath)
76+
}
77+
78+
for k := range tt.envVars {
79+
err := os.Unsetenv(k)
80+
assert.NoError(t, err)
81+
}
82+
})
83+
}
84+
}

0 commit comments

Comments
 (0)