Skip to content

Commit 2029131

Browse files
committed
Explicit generic types
Signed-off-by: Dr. Stefan Schimanski <[email protected]>
1 parent 0befadf commit 2029131

30 files changed

+2984
-342
lines changed

examples/namespace/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func main() {
109109
entryLog.Error(err, "unable to set up provider")
110110
os.Exit(1)
111111
}
112-
provider := namespace.NewNamespacedClusterProvider(cl)
112+
provider := namespace.New(cl)
113113

114114
// Setup a cluster-aware Manager, with the provider to lookup clusters.
115115
entryLog.Info("Setting up cluster-aware manager")
@@ -153,7 +153,7 @@ func main() {
153153

154154
entryLog.Info("Starting provider")
155155
go func() {
156-
if err := ignoreCanceled(provider.Start(ctx, mgr)); err != nil {
156+
if err := ignoreCanceled(provider.Run(ctx, mgr)); err != nil {
157157
entryLog.Error(err, "failed to start provider")
158158
os.Exit(1)
159159
}

go.mod

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ toolchain go1.23.4
66

77
require (
88
github.com/go-logr/logr v1.4.2
9+
github.com/onsi/ginkgo/v2 v2.21.0
10+
github.com/onsi/gomega v1.35.1
11+
golang.org/x/sys v0.26.0
912
k8s.io/api v0.32.0
13+
k8s.io/apiextensions-apiserver v0.32.0
1014
k8s.io/apimachinery v0.32.1
1115
k8s.io/client-go v0.32.0
1216
k8s.io/klog/v2 v2.130.1
@@ -22,15 +26,18 @@ require (
2226
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
2327
github.com/fsnotify/fsnotify v1.7.0 // indirect
2428
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
29+
github.com/go-logr/zapr v1.3.0 // indirect
2530
github.com/go-openapi/jsonpointer v0.21.0 // indirect
2631
github.com/go-openapi/jsonreference v0.20.2 // indirect
2732
github.com/go-openapi/swag v0.23.0 // indirect
33+
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
2834
github.com/gogo/protobuf v1.3.2 // indirect
2935
github.com/golang/protobuf v1.5.4 // indirect
3036
github.com/google/btree v1.1.3 // indirect
3137
github.com/google/gnostic-models v0.6.8 // indirect
3238
github.com/google/go-cmp v0.6.0 // indirect
3339
github.com/google/gofuzz v1.2.0 // indirect
40+
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
3441
github.com/google/uuid v1.6.0 // indirect
3542
github.com/josharian/intern v1.0.0 // indirect
3643
github.com/json-iterator/go v1.1.12 // indirect
@@ -45,19 +52,20 @@ require (
4552
github.com/prometheus/procfs v0.15.1 // indirect
4653
github.com/spf13/pflag v1.0.5 // indirect
4754
github.com/x448/float16 v0.8.4 // indirect
55+
go.uber.org/multierr v1.11.0 // indirect
56+
go.uber.org/zap v1.27.0 // indirect
4857
golang.org/x/net v0.30.0 // indirect
4958
golang.org/x/oauth2 v0.23.0 // indirect
5059
golang.org/x/sync v0.8.0 // indirect
51-
golang.org/x/sys v0.26.0 // indirect
5260
golang.org/x/term v0.25.0 // indirect
5361
golang.org/x/text v0.19.0 // indirect
5462
golang.org/x/time v0.7.0 // indirect
63+
golang.org/x/tools v0.26.0 // indirect
5564
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
5665
google.golang.org/protobuf v1.35.1 // indirect
5766
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
5867
gopkg.in/inf.v0 v0.9.1 // indirect
5968
gopkg.in/yaml.v3 v3.0.1 // indirect
60-
k8s.io/apiextensions-apiserver v0.32.0 // indirect
6169
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
6270
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
6371
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright 2021 The Kubernetes 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 addr_test
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
func TestAddr(t *testing.T) {
27+
t.Parallel()
28+
RegisterFailHandler(Fail)
29+
RunSpecs(t, "Addr Suite")
30+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
Copyright 2021 The Kubernetes 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 addr
18+
19+
import (
20+
"errors"
21+
"fmt"
22+
"io/fs"
23+
"net"
24+
"os"
25+
"path/filepath"
26+
"strings"
27+
"time"
28+
29+
"github.com/multicluster-runtime/multicluster-runtime/internal/forked/testing/flock"
30+
)
31+
32+
// TODO(directxman12): interface / release functionality for external port managers
33+
34+
const (
35+
portReserveTime = 2 * time.Minute
36+
portConflictRetry = 100
37+
portFilePrefix = "port-"
38+
)
39+
40+
var (
41+
cacheDir string
42+
)
43+
44+
func init() {
45+
baseDir, err := os.UserCacheDir()
46+
if err == nil {
47+
cacheDir = filepath.Join(baseDir, "kubebuilder-envtest")
48+
err = os.MkdirAll(cacheDir, 0o750)
49+
}
50+
if err != nil {
51+
// Either we didn't get a cache directory, or we can't use it
52+
baseDir = os.TempDir()
53+
cacheDir = filepath.Join(baseDir, "kubebuilder-envtest")
54+
err = os.MkdirAll(cacheDir, 0o750)
55+
}
56+
if err != nil {
57+
panic(err)
58+
}
59+
}
60+
61+
type portCache struct{}
62+
63+
func (c *portCache) add(port int) (bool, error) {
64+
// Remove outdated ports.
65+
if err := fs.WalkDir(os.DirFS(cacheDir), ".", func(path string, d fs.DirEntry, err error) error {
66+
if err != nil {
67+
return err
68+
}
69+
if d.IsDir() || !d.Type().IsRegular() || !strings.HasPrefix(path, portFilePrefix) {
70+
return nil
71+
}
72+
info, err := d.Info()
73+
if err != nil {
74+
// No-op if file no longer exists; may have been deleted by another
75+
// process/thread trying to allocate ports.
76+
if errors.Is(err, fs.ErrNotExist) {
77+
return nil
78+
}
79+
return err
80+
}
81+
if time.Since(info.ModTime()) > portReserveTime {
82+
if err := os.Remove(filepath.Join(cacheDir, path)); err != nil {
83+
// No-op if file no longer exists; may have been deleted by another
84+
// process/thread trying to allocate ports.
85+
if os.IsNotExist(err) {
86+
return nil
87+
}
88+
return err
89+
}
90+
}
91+
return nil
92+
}); err != nil {
93+
return false, err
94+
}
95+
// Try allocating new port, by acquiring a file.
96+
path := fmt.Sprintf("%s/%s%d", cacheDir, portFilePrefix, port)
97+
if err := flock.Acquire(path); errors.Is(err, flock.ErrAlreadyLocked) {
98+
return false, nil
99+
} else if err != nil {
100+
return false, err
101+
}
102+
return true, nil
103+
}
104+
105+
var cache = &portCache{}
106+
107+
func suggest(listenHost string) (*net.TCPListener, int, string, error) {
108+
if listenHost == "" {
109+
listenHost = "localhost"
110+
}
111+
addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(listenHost, "0"))
112+
if err != nil {
113+
return nil, -1, "", err
114+
}
115+
l, err := net.ListenTCP("tcp", addr)
116+
if err != nil {
117+
return nil, -1, "", err
118+
}
119+
return l, l.Addr().(*net.TCPAddr).Port,
120+
addr.IP.String(),
121+
nil
122+
}
123+
124+
// Suggest suggests an address a process can listen on. It returns
125+
// a tuple consisting of a free port and the hostname resolved to its IP.
126+
// It makes sure that new port allocated does not conflict with old ports
127+
// allocated within 1 minute.
128+
func Suggest(listenHost string) (int, string, error) {
129+
for i := 0; i < portConflictRetry; i++ {
130+
listener, port, resolvedHost, err := suggest(listenHost)
131+
if err != nil {
132+
return -1, "", err
133+
}
134+
defer listener.Close()
135+
if ok, err := cache.add(port); ok {
136+
return port, resolvedHost, nil
137+
} else if err != nil {
138+
return -1, "", err
139+
}
140+
}
141+
return -1, "", fmt.Errorf("no free ports found after %d retries", portConflictRetry)
142+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
Copyright 2021 The Kubernetes 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 addr_test
18+
19+
import (
20+
"net"
21+
"strconv"
22+
23+
. "github.com/onsi/ginkgo/v2"
24+
. "github.com/onsi/gomega"
25+
26+
"sigs.k8s.io/controller-runtime/pkg/internal/testing/addr"
27+
)
28+
29+
var _ = Describe("SuggestAddress", func() {
30+
It("returns a free port and an address to bind to", func() {
31+
port, host, err := addr.Suggest("")
32+
33+
Expect(err).NotTo(HaveOccurred())
34+
Expect(host).To(Or(Equal("127.0.0.1"), Equal("::1")))
35+
Expect(port).NotTo(Equal(0))
36+
37+
addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(host, strconv.Itoa(port)))
38+
Expect(err).NotTo(HaveOccurred())
39+
l, err := net.ListenTCP("tcp", addr)
40+
defer func() {
41+
Expect(l.Close()).To(Succeed())
42+
}()
43+
Expect(err).NotTo(HaveOccurred())
44+
})
45+
46+
It("supports an explicit listenHost", func() {
47+
port, host, err := addr.Suggest("localhost")
48+
49+
Expect(err).NotTo(HaveOccurred())
50+
Expect(host).To(Or(Equal("127.0.0.1"), Equal("::1")))
51+
Expect(port).NotTo(Equal(0))
52+
53+
addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(host, strconv.Itoa(port)))
54+
Expect(err).NotTo(HaveOccurred())
55+
l, err := net.ListenTCP("tcp", addr)
56+
defer func() {
57+
Expect(l.Close()).To(Succeed())
58+
}()
59+
Expect(err).NotTo(HaveOccurred())
60+
})
61+
62+
It("supports a 0.0.0.0 listenHost", func() {
63+
port, host, err := addr.Suggest("0.0.0.0")
64+
65+
Expect(err).NotTo(HaveOccurred())
66+
Expect(host).To(Equal("0.0.0.0"))
67+
Expect(port).NotTo(Equal(0))
68+
69+
addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(host, strconv.Itoa(port)))
70+
Expect(err).NotTo(HaveOccurred())
71+
l, err := net.ListenTCP("tcp", addr)
72+
defer func() {
73+
Expect(l.Close()).To(Succeed())
74+
}()
75+
Expect(err).NotTo(HaveOccurred())
76+
})
77+
})

internal/forked/testing/flock/doc.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
Copyright 2021 The Kubernetes 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 flock is copied from k8s.io/kubernetes/pkg/util/flock to avoid
18+
// importing k8s.io/kubernetes as a dependency.
19+
//
20+
// Provides file locking functionalities on unix systems.
21+
package flock
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
Copyright 2021 The Kubernetes 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 flock
18+
19+
import "errors"
20+
21+
var (
22+
// ErrAlreadyLocked is returned when the file is already locked.
23+
ErrAlreadyLocked = errors.New("the file is already locked")
24+
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// +build !linux,!darwin,!freebsd,!openbsd,!netbsd,!dragonfly
2+
3+
/*
4+
Copyright 2016 The Kubernetes Authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package flock
20+
21+
// Acquire is not implemented on non-unix systems.
22+
func Acquire(path string) error {
23+
return nil
24+
}

0 commit comments

Comments
 (0)