Skip to content

Commit c9cb008

Browse files
committed
Add support for dedicated chaincode nodes
Also fixes issues when chaincode pods do not start See #228 Signed-off-by: James Taylor <[email protected]>
1 parent ec52468 commit c9cb008

19 files changed

+495
-114
lines changed

cmd/run.go

Lines changed: 127 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,86 +5,175 @@ package cmd
55
import (
66
"context"
77
"os"
8-
"strconv"
8+
"time"
99

1010
"github.com/hyperledger-labs/fabric-builder-k8s/internal/builder"
1111
"github.com/hyperledger-labs/fabric-builder-k8s/internal/log"
1212
"github.com/hyperledger-labs/fabric-builder-k8s/internal/util"
13-
"k8s.io/apimachinery/pkg/api/validation"
13+
apivalidation "k8s.io/apimachinery/pkg/api/validation"
14+
"k8s.io/apimachinery/pkg/util/validation"
1415
)
1516

16-
func Run() int {
17-
const (
18-
expectedArgsLength = 3
19-
buildOutputDirectoryArg = 1
20-
runMetadataDirectoryArg = 2
21-
maximumKubeNamePrefixLength = 30
22-
)
23-
24-
debug, _ := strconv.ParseBool(util.GetOptionalEnv(util.DebugVariable, "false"))
25-
ctx := log.NewCmdContext(context.Background(), debug)
26-
logger := log.New(ctx)
27-
28-
if len(os.Args) != expectedArgsLength {
29-
logger.Println("Expected BUILD_OUTPUT_DIR and RUN_METADATA_DIR arguments")
30-
31-
return 1
32-
}
33-
34-
buildOutputDirectory := os.Args[buildOutputDirectoryArg]
35-
runMetadataDirectory := os.Args[runMetadataDirectoryArg]
36-
37-
logger.Debugf("Build output directory: %s", buildOutputDirectory)
38-
logger.Debugf("Run metadata directory: %s", runMetadataDirectory)
39-
17+
//nolint:nonamedreturns // using the ok bool convention to indicate errors
18+
func getPeerID(logger *log.CmdLogger) (peerID string, ok bool) {
4019
peerID, err := util.GetRequiredEnv(util.PeerIDVariable)
4120
if err != nil {
4221
logger.Printf("Expected %s environment variable\n", util.PeerIDVariable)
4322

44-
return 1
23+
return peerID, false
4524
}
4625

4726
logger.Debugf("%s=%s", util.PeerIDVariable, peerID)
4827

28+
return peerID, true
29+
}
30+
31+
func getKubeconfigPath(logger *log.CmdLogger) string {
4932
kubeconfigPath := util.GetOptionalEnv(util.KubeconfigPathVariable, "")
5033
logger.Debugf("%s=%s", util.KubeconfigPathVariable, kubeconfigPath)
5134

35+
return kubeconfigPath
36+
}
37+
38+
func getKubeNamespace(logger *log.CmdLogger) string {
5239
kubeNamespace := util.GetOptionalEnv(util.ChaincodeNamespaceVariable, "")
5340
logger.Debugf("%s=%s", util.ChaincodeNamespaceVariable, kubeNamespace)
5441

5542
if kubeNamespace == "" {
43+
var err error
44+
5645
kubeNamespace, err = util.GetKubeNamespace()
5746
if err != nil {
47+
logger.Debugf("Error getting namespace: %+v\n", util.DefaultNamespace, err)
5848
kubeNamespace = util.DefaultNamespace
5949
}
50+
51+
logger.Debugf("Using default namespace: %s\n", util.DefaultNamespace)
6052
}
6153

54+
return kubeNamespace
55+
}
56+
57+
//nolint:nonamedreturns // using the ok bool convention to indicate errors
58+
func getKubeNodeRole(logger *log.CmdLogger) (kubeNodeRole string, ok bool) {
59+
kubeNodeRole = util.GetOptionalEnv(util.ChaincodeNodeRoleVariable, "")
60+
logger.Debugf("%s=%s", util.ChaincodeNodeRoleVariable, kubeNodeRole)
61+
62+
// TODO: are valid taint values the same?!
63+
if msgs := validation.IsValidLabelValue(kubeNodeRole); len(msgs) > 0 {
64+
logger.Printf("The %s environment variable must be a valid Kubernetes label value: %s", util.ChaincodeNodeRoleVariable, msgs[0])
65+
66+
return kubeNodeRole, false
67+
}
68+
69+
return kubeNodeRole, true
70+
}
71+
72+
func getKubeServiceAccount(logger *log.CmdLogger) string {
6273
kubeServiceAccount := util.GetOptionalEnv(util.ChaincodeServiceAccountVariable, util.DefaultServiceAccountName)
6374
logger.Debugf("%s=%s", util.ChaincodeServiceAccountVariable, kubeServiceAccount)
6475

65-
kubeNamePrefix := util.GetOptionalEnv(util.ObjectNamePrefixVariable, util.DefaultObjectNamePrefix)
76+
return kubeServiceAccount
77+
}
78+
79+
//nolint:nonamedreturns // using the ok bool convention to indicate errors
80+
func getKubeNamePrefix(logger *log.CmdLogger) (kubeNamePrefix string, ok bool) {
81+
const maximumKubeNamePrefixLength = 30
82+
83+
kubeNamePrefix = util.GetOptionalEnv(util.ObjectNamePrefixVariable, util.DefaultObjectNamePrefix)
6684
logger.Debugf("%s=%s", util.ObjectNamePrefixVariable, kubeNamePrefix)
6785

6886
if len(kubeNamePrefix) > maximumKubeNamePrefixLength {
69-
logger.Printf("The FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX environment variable must be a maximum of 30 characters")
87+
logger.Printf("The %s environment variable must be a maximum of 30 characters", util.ObjectNamePrefixVariable)
88+
89+
return kubeNamePrefix, false
90+
}
91+
92+
if msgs := apivalidation.NameIsDNS1035Label(kubeNamePrefix, true); len(msgs) > 0 {
93+
logger.Printf("The %s environment variable must be a valid DNS-1035 label: %s", util.ObjectNamePrefixVariable, msgs[0])
94+
95+
return kubeNamePrefix, false
96+
}
97+
98+
return kubeNamePrefix, true
99+
}
100+
101+
//nolint:nonamedreturns // using the ok bool convention to indicate errors
102+
func getChaincodeStartTimeout(logger *log.CmdLogger) (chaincodeStartTimeoutDuration time.Duration, ok bool) {
103+
chaincodeStartTimeout := util.GetOptionalEnv(util.ChaincodeStartTimeoutVariable, util.DefaultStartTimeout)
104+
logger.Debugf("%s=%s", util.ChaincodeStartTimeoutVariable, chaincodeStartTimeout)
105+
106+
chaincodeStartTimeoutDuration, err := time.ParseDuration(chaincodeStartTimeout)
107+
if err != nil {
108+
logger.Printf("The %s environment variable must be a valid Go duration string, e.g. 3m40s: %v", util.ChaincodeStartTimeoutVariable, err)
109+
110+
return 0 * time.Minute, false
111+
}
112+
113+
return chaincodeStartTimeoutDuration, true
114+
}
115+
116+
func Run() int {
117+
const (
118+
expectedArgsLength = 3
119+
buildOutputDirectoryArg = 1
120+
runMetadataDirectoryArg = 2
121+
)
122+
123+
debug := util.GetOptionalEnv(util.DebugVariable, "false")
124+
ctx := log.NewCmdContext(context.Background(), debug == "true")
125+
logger := log.New(ctx)
126+
127+
if len(os.Args) != expectedArgsLength {
128+
logger.Println("Expected BUILD_OUTPUT_DIR and RUN_METADATA_DIR arguments")
70129

71130
return 1
72131
}
73132

74-
if msgs := validation.NameIsDNS1035Label(kubeNamePrefix, true); len(msgs) > 0 {
75-
logger.Printf("The FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX environment variable must be a valid DNS-1035 label: %s", msgs[0])
133+
buildOutputDirectory := os.Args[buildOutputDirectoryArg]
134+
runMetadataDirectory := os.Args[runMetadataDirectoryArg]
135+
136+
logger.Debugf("Build output directory: %s", buildOutputDirectory)
137+
logger.Debugf("Run metadata directory: %s", runMetadataDirectory)
138+
139+
//nolint:varnamelen // using the ok bool convention to indicate errors
140+
var ok bool
141+
142+
peerID, ok := getPeerID(logger)
143+
if !ok {
144+
return 1
145+
}
146+
147+
kubeconfigPath := getKubeconfigPath(logger)
148+
kubeNamespace := getKubeNamespace(logger)
149+
150+
kubeNodeRole, ok := getKubeNodeRole(logger)
151+
if !ok {
152+
return 1
153+
}
154+
155+
kubeServiceAccount := getKubeServiceAccount(logger)
156+
157+
kubeNamePrefix, ok := getKubeNamePrefix(logger)
158+
if !ok {
159+
return 1
160+
}
76161

162+
chaincodeStartTimeout, ok := getChaincodeStartTimeout(logger)
163+
if !ok {
77164
return 1
78165
}
79166

80167
run := &builder.Run{
81-
BuildOutputDirectory: buildOutputDirectory,
82-
RunMetadataDirectory: runMetadataDirectory,
83-
PeerID: peerID,
84-
KubeconfigPath: kubeconfigPath,
85-
KubeNamespace: kubeNamespace,
86-
KubeServiceAccount: kubeServiceAccount,
87-
KubeNamePrefix: kubeNamePrefix,
168+
BuildOutputDirectory: buildOutputDirectory,
169+
RunMetadataDirectory: runMetadataDirectory,
170+
PeerID: peerID,
171+
KubeconfigPath: kubeconfigPath,
172+
KubeNamespace: kubeNamespace,
173+
KubeNodeRole: kubeNodeRole,
174+
KubeServiceAccount: kubeServiceAccount,
175+
KubeNamePrefix: kubeNamePrefix,
176+
ChaincodeStartTimeout: chaincodeStartTimeout,
88177
}
89178

90179
if err := run.Run(ctx); err != nil {

cmd/run/main_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,28 @@ var _ = Describe("Main", func() {
4343
),
4444
)
4545

46+
DescribeTable("Running the run command produces the correct error for invalid FABRIC_K8S_BUILDER_NODE_ROLE environment variable values",
47+
func(kubeNodeRoleValue, expectedErrorMessage string) {
48+
args := []string{"BUILD_OUTPUT_DIR", "RUN_METADATA_DIR"}
49+
command := exec.Command(runCmdPath, args...)
50+
command.Env = append(os.Environ(),
51+
"CORE_PEER_ID=core-peer-id-abcdefghijklmnopqrstuvwxyz-0123456789",
52+
"FABRIC_K8S_BUILDER_NODE_ROLE="+kubeNodeRoleValue,
53+
)
54+
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
55+
Expect(err).NotTo(HaveOccurred())
56+
57+
Eventually(session).Should(gexec.Exit(1))
58+
Eventually(
59+
session.Err,
60+
).Should(gbytes.Say(expectedErrorMessage))
61+
},
62+
Entry("When the FABRIC_K8S_BUILDER_NODE_ROLE is too long", "long-node-role-is-looooooooooooooooooooooooooooooooooooooooooong", `run \[\d+\]: The FABRIC_K8S_BUILDER_NODE_ROLE environment variable must be a valid Kubernetes label value: must be no more than 63 characters`),
63+
Entry("When the FABRIC_K8S_BUILDER_NODE_ROLE contains invalid characters", "invalid*value", `run \[\d+\]: The FABRIC_K8S_BUILDER_NODE_ROLE environment variable must be a valid Kubernetes label value: a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '\.', and must start and end with an alphanumeric character`),
64+
Entry("When the FABRIC_K8S_BUILDER_NODE_ROLE does not start with an alphanumeric character", ".role", `run \[\d+\]: The FABRIC_K8S_BUILDER_NODE_ROLE environment variable must be a valid Kubernetes label value: a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '\.', and must start and end with an alphanumeric character`),
65+
Entry("When the FABRIC_K8S_BUILDER_NODE_ROLE does not end with an alphanumeric character", "role-", `run \[\d+\]: The FABRIC_K8S_BUILDER_NODE_ROLE environment variable must be a valid Kubernetes label value: a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '\.', and must start and end with an alphanumeric character`),
66+
)
67+
4668
DescribeTable("Running the run command produces the correct error for invalid FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX environment variable values",
4769
func(kubeNamePrefixValue, expectedErrorMessage string) {
4870
args := []string{"BUILD_OUTPUT_DIR", "RUN_METADATA_DIR"}
@@ -64,4 +86,24 @@ var _ = Describe("Main", func() {
6486
Entry("When the FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX starts with a number", "1prefix", `run \[\d+\]: The FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX environment variable must be a valid DNS-1035 label: a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character`),
6587
Entry("When the FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX starts with a dash", "-prefix", `run \[\d+\]: The FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX environment variable must be a valid DNS-1035 label: a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character`),
6688
)
89+
90+
DescribeTable("Running the run command produces the correct error for invalid FABRIC_K8S_BUILDER_START_TIMEOUT environment variable values",
91+
func(chaincodeStartTimeoutValue, expectedErrorMessage string) {
92+
args := []string{"BUILD_OUTPUT_DIR", "RUN_METADATA_DIR"}
93+
command := exec.Command(runCmdPath, args...)
94+
command.Env = append(os.Environ(),
95+
"CORE_PEER_ID=core-peer-id-abcdefghijklmnopqrstuvwxyz-0123456789",
96+
"FABRIC_K8S_BUILDER_START_TIMEOUT="+chaincodeStartTimeoutValue,
97+
)
98+
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
99+
Expect(err).NotTo(HaveOccurred())
100+
101+
Eventually(session).Should(gexec.Exit(1))
102+
Eventually(
103+
session.Err,
104+
).Should(gbytes.Say(expectedErrorMessage))
105+
},
106+
Entry("When the FABRIC_K8S_BUILDER_START_TIMEOUT is missing a duration unit", "3", `run \[\d+\]: The FABRIC_K8S_BUILDER_START_TIMEOUT environment variable must be a valid Go duration string, e\.g\. 3m40s: time: missing unit in duration "3"`),
107+
Entry("When the FABRIC_K8S_BUILDER_START_TIMEOUT is not a valid duration string", "three minutes", `run \[\d+\]: The FABRIC_K8S_BUILDER_START_TIMEOUT environment variable must be a valid Go duration string, e\.g\. 3m40s: time: invalid duration "three minutes"`),
108+
)
67109
})
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Dedicated nodes
2+
3+
By default, the k8s builder does not implement any Kubernetes node scheduling strategies.
4+
5+
The `FABRIC_K8S_BUILDER_NODE_ROLE` environment variable can be used to schedule chaincode on dedicated Kubernetes nodes.
6+
Chaincode pods will be configured with an affinity for nodes with the `fabric-builder-k8s-role=<node_role>` label, and will tolerate nodes with the `fabric-builder-k8s-role=<node_role>:NoSchedule` taint.
7+
8+
For example, if `FABRIC_K8S_BUILDER_NODE_ROLE` is set to `chaincode`, use the following `kubectl` commands to configure a dedicated chaincode node `ccnode`.
9+
10+
```shell
11+
kubectl label nodes ccnode fabric-builder-k8s-role=chaincode
12+
kubectl taint nodes ccnode fabric-builder-k8s-role=chaincode:NoSchedule
13+
```
14+
15+
More complex requirements should be handled with Dynamic Admission Control using a Mutating Webhook.
16+
For example, you could use a webhook to assign node affinity and tolerations to all pods in a `chaincode` namespace.

docs/configuring/overview.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ External builders are configured in the `core.yaml` file, for example:
1414
- CORE_PEER_ID
1515
- FABRIC_K8S_BUILDER_DEBUG
1616
- FABRIC_K8S_BUILDER_NAMESPACE
17+
- FABRIC_K8S_BUILDER_NODE_ROLE
1718
- FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX
1819
- FABRIC_K8S_BUILDER_SERVICE_ACCOUNT
20+
- FABRIC_K8S_BUILDER_START_TIMEOUT
1921
- KUBERNETES_SERVICE_HOST
2022
- KUBERNETES_SERVICE_PORT
2123
```
@@ -30,8 +32,10 @@ The k8s builder is configured using the following environment variables.
3032
| ------------------------------------- | -------------------------------- | ---------------------------------------------------- |
3133
| CORE_PEER_ID | | The Fabric peer ID (required) |
3234
| FABRIC_K8S_BUILDER_NAMESPACE | The peer namespace or `default` | The Kubernetes namespace to run chaincode with |
35+
| FABRIC_K8S_BUILDER_NODE_ROLE | | Use dedicated Kubernetes nodes to run chaincode |
3336
| FABRIC_K8S_BUILDER_OBJECT_NAME_PREFIX | `hlfcc` | Eye-catcher prefix for Kubernetes object names |
3437
| FABRIC_K8S_BUILDER_SERVICE_ACCOUNT | `default` | The Kubernetes service account to run chaincode with |
38+
| FABRIC_K8S_BUILDER_START_TIMEOUT | `3m` | The timeout when waiting for chaincode pods to start |
3539
| FABRIC_K8S_BUILDER_DEBUG | `false` | Set to `true` to enable k8s builder debug messages |
3640

3741
The k8s builder can be run in cluster using the `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` environment variables, or it can connect using a `KUBECONFIG_PATH` environment variable.

go.mod

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ require (
3030
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
3131
github.com/google/uuid v1.6.0 // indirect
3232
github.com/gorilla/websocket v1.5.0 // indirect
33-
github.com/itchyny/gojq v0.12.13 // indirect
34-
github.com/itchyny/timefmt-go v0.1.5 // indirect
3533
github.com/josharian/intern v1.0.0 // indirect
3634
github.com/mailru/easyjson v0.7.7 // indirect
3735
github.com/moby/spdystream v0.4.0 // indirect
@@ -47,12 +45,10 @@ require (
4745
golang.org/x/sync v0.8.0 // indirect
4846
golang.org/x/tools v0.26.0 // indirect
4947
k8s.io/component-base v0.31.1 // indirect
50-
mvdan.cc/sh/v3 v3.7.0 // indirect
5148
sigs.k8s.io/controller-runtime v0.19.0 // indirect
5249
)
5350

5451
require (
55-
github.com/bitfield/script v0.23.0
5652
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
5753
github.com/go-logr/logr v1.4.2 // indirect
5854
github.com/gogo/protobuf v1.3.2 // indirect

go.sum

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
22
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
33
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
44
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
5-
github.com/bitfield/script v0.23.0 h1:N0R5yLEl6wJIS9PR/A6xXwjMsplMubyxdi05N5l0X28=
6-
github.com/bitfield/script v0.23.0/go.mod h1:fv+6x4OzVsRs6qAlc7wiGq8fq1b5orhtQdtW0dwjUHI=
75
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
86
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
97
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
@@ -16,8 +14,6 @@ github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+
1614
github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
1715
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
1816
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
19-
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
20-
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
2117
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
2218
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
2319
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
@@ -52,10 +48,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
5248
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
5349
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
5450
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
55-
github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU=
56-
github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4=
57-
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
58-
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
5951
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
6052
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
6153
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -191,8 +183,6 @@ k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7F
191183
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
192184
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
193185
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
194-
mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg=
195-
mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=
196186
sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q=
197187
sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
198188
sigs.k8s.io/e2e-framework v0.5.0 h1:YLhk8R7EHuTFQAe6Fxy5eBzn5Vb+yamR5u8MH1Rq3cE=

0 commit comments

Comments
 (0)