Skip to content

Commit eaeb0fe

Browse files
committed
Add wip bits of ldap operator, start using flake-parts
1 parent 1682d05 commit eaeb0fe

21 files changed

+1724
-152
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ result
99
.ghtoken
1010
cue.mod/gen
1111
secrets*.yaml
12+
.gradle
13+
.classpath
14+
.factorypath
15+
.settings
16+
.project

flake.lock

+37
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

+213-152
Large diffs are not rendered by default.

k8s/cert-manager/cert-manager.cue

+12
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ kustomizations: {
3939
"self-signed": clusterissuer.#ClusterIssuer & {
4040
spec: selfSigned: {}
4141
}
42+
"letsencrypt": this=(clusterissuer.#ClusterIssuer & {
43+
spec: acme: {
44+
45+
server: "https://acme-v02.api.letsencrypt.org/directory"
46+
privateKeySecretRef: {
47+
name: "\(this.metadata.name)-key"
48+
}
49+
solvers: [{
50+
dns01: digitalocean: tokenSecretRef: { name: "digitalocean-token", key: "access-token" }
51+
}]
52+
}
53+
})
4254
}
4355
}
4456

src/elector/cmd/elector/main.go

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"os"
6+
"log"
7+
"syscall"
8+
"fmt"
9+
"time"
10+
"net/http"
11+
"os/signal"
12+
le "k8s.io/client-go/tools/leaderelection"
13+
rl "k8s.io/client-go/tools/leaderelection/resourcelock"
14+
"k8s.io/apimachinery/pkg/types"
15+
"k8s.io/client-go/kubernetes"
16+
discoveryv1client "k8s.io/client-go/kubernetes/typed/discovery/v1"
17+
discoveryv1app "k8s.io/client-go/applyconfigurations/discovery/v1"
18+
discoveryv1 "k8s.io/api/discovery/v1"
19+
corev1app "k8s.io/client-go/applyconfigurations/core/v1"
20+
corev1 "k8s.io/api/core/v1"
21+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
"k8s.io/client-go/rest"
23+
)
24+
25+
type Callbacks struct {
26+
PodName string
27+
PodUID string
28+
PodIP string
29+
NodeName string
30+
ServiceName string
31+
Namespace string
32+
EndpointSlices discoveryv1client.EndpointSliceInterface
33+
}
34+
35+
func (c *Callbacks) OnStartedLeading(ctx context.Context) {
36+
log.Println(fmt.Sprintf("Started leading"))
37+
apply := discoveryv1app.EndpointSlice(c.ServiceName, c.Namespace).
38+
WithLabels(map[string]string{"kubernetes.io/service-name": c.ServiceName}).
39+
WithAddressType(discoveryv1.AddressTypeIPv4).
40+
WithPorts(discoveryv1app.EndpointPort().
41+
WithName("ldaps").
42+
WithProtocol(corev1.ProtocolTCP).
43+
WithPort(636)).
44+
WithEndpoints(discoveryv1app.Endpoint().
45+
WithAddresses(c.PodIP).
46+
WithNodeName(c.NodeName).
47+
WithConditions(discoveryv1app.EndpointConditions().
48+
WithReady(true).
49+
WithServing(true).
50+
WithTerminating(false)).
51+
WithTargetRef(corev1app.ObjectReference().
52+
WithKind("Pod").
53+
WithName(c.PodName).
54+
WithNamespace(c.Namespace).
55+
WithUID(types.UID(c.PodUID))))
56+
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
57+
defer cancel()
58+
c.EndpointSlices.Apply(ctx, apply, metav1.ApplyOptions{FieldManager: "openldap-leader"})
59+
log.Println(fmt.Sprintf("Updated EndpointSlice"))
60+
}
61+
62+
func (c *Callbacks) OnStoppedLeading() {
63+
log.Println(fmt.Sprintf("Stopped leading"))
64+
}
65+
66+
func (c *Callbacks) OnNewLeader(identity string) {
67+
log.Println(fmt.Sprintf("New leader: %s", identity))
68+
}
69+
70+
type Handler func(http.ResponseWriter, *http.Request)
71+
72+
func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
73+
h(w, req)
74+
}
75+
76+
func main() {
77+
podName := os.Getenv("POD_NAME")
78+
podUID := os.Getenv("POD_UID")
79+
podIP := os.Getenv("POD_IP")
80+
namespace := os.Getenv("NAMESPACE")
81+
nodeName := os.Getenv("NODE_NAME")
82+
serviceName := os.Getenv("SERVICE_NAME")
83+
84+
lockType := rl.LeasesResourceLock
85+
config, err := rest.InClusterConfig()
86+
if err != nil {
87+
panic(err)
88+
}
89+
client := kubernetes.NewForConfigOrDie(config)
90+
lock, err := rl.New(lockType, namespace, serviceName, client.CoreV1(), client.CoordinationV1(), rl.ResourceLockConfig{
91+
Identity: podName,
92+
})
93+
if err != nil {
94+
panic(err)
95+
}
96+
97+
callbacks := Callbacks{
98+
PodName: podName,
99+
PodUID: podUID,
100+
PodIP: podIP,
101+
NodeName: nodeName,
102+
ServiceName: serviceName,
103+
Namespace: namespace,
104+
EndpointSlices: client.DiscoveryV1().EndpointSlices(namespace),
105+
}
106+
107+
elector, err := le.NewLeaderElector(le.LeaderElectionConfig{
108+
Lock: lock,
109+
LeaseDuration: 15 * time.Second,
110+
RenewDeadline: 10 * time.Second,
111+
RetryPeriod: 2 * time.Second,
112+
ReleaseOnCancel: true,
113+
Callbacks: le.LeaderCallbacks{
114+
OnStartedLeading: callbacks.OnStartedLeading,
115+
OnStoppedLeading: callbacks.OnStoppedLeading,
116+
OnNewLeader: callbacks.OnNewLeader,
117+
},
118+
})
119+
if err != nil {
120+
panic(err)
121+
}
122+
123+
ctx, cancel := context.WithCancel(context.Background())
124+
defer cancel()
125+
126+
canceled := false
127+
128+
go func() {
129+
for !canceled {
130+
elector.Run(ctx)
131+
}
132+
}()
133+
134+
sigint := make(chan os.Signal, 1)
135+
signal.Notify(sigint, os.Interrupt)
136+
sigkill := make(chan os.Signal, 1)
137+
signal.Notify(sigkill, os.Kill)
138+
sigterm := make(chan os.Signal, 1)
139+
signal.Notify(sigterm, syscall.SIGTERM)
140+
141+
done := make(chan os.Signal, 1)
142+
143+
go func() {
144+
http.ListenAndServe("0.0.0.0:80", Handler(func(w http.ResponseWriter, req *http.Request) {
145+
log.Println("Stopping leader election", req)
146+
close(done)
147+
w.WriteHeader(http.StatusNoContent)
148+
_, _ = w.Write([]byte{})
149+
}))
150+
}()
151+
152+
defer func() { log.Println("Shutting down") }()
153+
154+
select {
155+
case <-sigint:
156+
return
157+
case <-sigkill:
158+
return
159+
case <-sigterm:
160+
return
161+
case <-done:
162+
canceled = true
163+
cancel()
164+
}
165+
166+
for {
167+
select {
168+
case <-sigint:
169+
return
170+
case <-sigkill:
171+
return
172+
case <-sigterm:
173+
return
174+
}
175+
}
176+
}

src/elector/cmd/pre-stop/main.go

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"log"
7+
"net/http"
8+
"os"
9+
"time"
10+
11+
discoveryv1 "k8s.io/api/discovery/v1"
12+
"k8s.io/client-go/kubernetes"
13+
"k8s.io/client-go/rest"
14+
"k8s.io/client-go/tools/cache"
15+
"k8s.io/client-go/tools/watch"
16+
"k8s.io/apimachinery/pkg/fields"
17+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18+
machinerywatch "k8s.io/apimachinery/pkg/watch"
19+
)
20+
21+
func main() {
22+
namespace := os.Getenv("NAMESPACE")
23+
serviceName := os.Getenv("EXTERNAL_SERVICE_NAME")
24+
podIP := os.Getenv("POD_IP")
25+
26+
client := http.Client{
27+
Timeout: 30 * time.Second,
28+
}
29+
_, err := client.Post("http://localhost/stop-election", "application/json", bytes.NewReader([]byte{}))
30+
if err != nil {
31+
panic(err)
32+
}
33+
34+
config, err := rest.InClusterConfig()
35+
if err != nil {
36+
panic(err)
37+
}
38+
kclient := kubernetes.NewForConfigOrDie(config)
39+
40+
condition := func(slice *discoveryv1.EndpointSlice) (bool, error) {
41+
log.Println(slice)
42+
for _, endpoint := range slice.Endpoints {
43+
for _, address := range endpoint.Addresses {
44+
log.Println("POD_IP =", podIP)
45+
log.Println("comparing to", address)
46+
if address != podIP {
47+
log.Println("Found other address, done!")
48+
return true, nil
49+
}
50+
}
51+
}
52+
return false, nil
53+
}
54+
55+
watch.UntilWithSync(
56+
context.Background(),
57+
cache.NewListWatchFromClient(
58+
kclient.DiscoveryV1().RESTClient(),
59+
"endpointslices",
60+
namespace,
61+
fields.OneTermEqualSelector(metav1.ObjectNameField, serviceName),
62+
),
63+
&discoveryv1.EndpointSlice{},
64+
func(store cache.Store) (bool, error) {
65+
obj, present, err := store.GetByKey(namespace + "/" + serviceName)
66+
if !present || err != nil{
67+
return false, nil
68+
}
69+
slice, ok := obj.(*discoveryv1.EndpointSlice)
70+
if !ok {
71+
return false, nil
72+
}
73+
return condition(slice)
74+
},
75+
func(event machinerywatch.Event) (bool, error) {
76+
if slice, ok := event.Object.(*discoveryv1.EndpointSlice); ok {
77+
return condition(slice)
78+
} else {
79+
return false, nil
80+
}
81+
},
82+
)
83+
}

src/elector/go.mod

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
module github.com/pythoner6/netserv/src/openldap-sidecar
2+
3+
go 1.21.4
4+
5+
require (
6+
k8s.io/api v0.29.0
7+
k8s.io/apimachinery v0.29.0
8+
k8s.io/client-go v0.29.0
9+
)
10+
11+
require (
12+
github.com/davecgh/go-spew v1.1.1 // indirect
13+
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
14+
github.com/go-logr/logr v1.3.0 // indirect
15+
github.com/go-openapi/jsonpointer v0.19.6 // indirect
16+
github.com/go-openapi/jsonreference v0.20.2 // indirect
17+
github.com/go-openapi/swag v0.22.3 // indirect
18+
github.com/gogo/protobuf v1.3.2 // indirect
19+
github.com/golang/protobuf v1.5.3 // indirect
20+
github.com/google/gnostic-models v0.6.8 // indirect
21+
github.com/google/go-cmp v0.6.0 // indirect
22+
github.com/google/gofuzz v1.2.0 // indirect
23+
github.com/google/uuid v1.3.0 // indirect
24+
github.com/josharian/intern v1.0.0 // indirect
25+
github.com/json-iterator/go v1.1.12 // indirect
26+
github.com/mailru/easyjson v0.7.7 // indirect
27+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
28+
github.com/modern-go/reflect2 v1.0.2 // indirect
29+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
30+
golang.org/x/net v0.17.0 // indirect
31+
golang.org/x/oauth2 v0.10.0 // indirect
32+
golang.org/x/sys v0.13.0 // indirect
33+
golang.org/x/term v0.13.0 // indirect
34+
golang.org/x/text v0.13.0 // indirect
35+
golang.org/x/time v0.3.0 // indirect
36+
google.golang.org/appengine v1.6.7 // indirect
37+
google.golang.org/protobuf v1.31.0 // indirect
38+
gopkg.in/inf.v0 v0.9.1 // indirect
39+
gopkg.in/yaml.v2 v2.4.0 // indirect
40+
gopkg.in/yaml.v3 v3.0.1 // indirect
41+
k8s.io/klog/v2 v2.110.1 // indirect
42+
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
43+
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
44+
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
45+
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
46+
sigs.k8s.io/yaml v1.3.0 // indirect
47+
)

0 commit comments

Comments
 (0)