11package controllers
22
33import (
4- "bytes"
54 "context"
6- encjson "encoding/json"
75 "strconv"
8- tmpl "text/template"
96
107 corev1 "k8s.io/api/core/v1"
118 "k8s.io/apimachinery/pkg/api/resource"
129 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13- "k8s.io/apimachinery/pkg/util/json"
1410 ctrl "sigs.k8s.io/controller-runtime"
1511
12+ "github.com/ipfs/kubo/config"
1613 "github.com/libp2p/go-libp2p-core/peer"
1714 ma "github.com/multiformats/go-multiaddr"
1815 clusterv1alpha1 "github.com/redhat-et/ipfs-operator/api/v1alpha1"
16+ "github.com/redhat-et/ipfs-operator/controllers/scripts"
1917 "sigs.k8s.io/controller-runtime/pkg/client"
2018 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2119 ctrllog "sigs.k8s.io/controller-runtime/pkg/log"
2220)
2321
24- type configureIpfsOpts struct {
25- StorageMax string
26- RelayClientJSON string
27- PeersJSON string
28- }
29-
30- var (
31- entrypoint = `
32- #!/bin/sh
33- user=ipfs
34-
35- # This is a custom entrypoint for k8s designed to connect to the bootstrap
36- # node running in the cluster. It has been set up using a configmap to
37- # allow changes on the fly.
38-
39- ######################################
40- # Prints out the given message to STDOUT
41- # with timestamped formatting.
42- # Globals:
43- # None
44- # Arguments:
45- # msg: (string) message to print
46- # Returns:
47- # None
48- ######################################
49- log() {
50- msg="$1"
51- # get the current time
52- time=$(date +%Y-%m-%dT%H:%M:%S%z)
53- # print the message with printf
54- printf "[%s] %s\n" "${time}" "${msg}"
55- }
56-
57- ######################################
58- # This is a custom entrypoint for k8s designed to connect to the bootstrap
59- # node running in the cluster. It has been set up using a configmap to
60- # allow changes on the fly.
61- #
62- # Globals:
63- # BOOTSTRAP_PEER_ID (string) the peer id of the bootstrap node
64- # BOOTSTRAP_PEER_PRIV_KEY (string) the private key of the bootstrap node
65- # BOOTSTRAP_ADDR (string) the address of the bootstrap node
66- # SVC_NAME (string) the name of the service to connect to
67- ######################################
68- run_ipfs_cluster() {
69- if [ ! -f /data/ipfs-cluster/service.json ]; then
70- log "📰 no service.json found, creating one"
71- ipfs-cluster-service init --consensus crdt
72- fi
73-
74- log "🔍 reading hostname"
75- PEER_HOSTNAME=$(cat /proc/sys/kernel/hostname)
76- log "starting ipfs-cluster on ${PEER_HOSTNAME}"
77-
78- grep -q ".*-0$" /proc/sys/kernel/hostname
79- if [ $? -eq 0 ]; then
80- log "starting ipfs-cluster using the provided peer ID and private key"
81- CLUSTER_ID="${BOOTSTRAP_PEER_ID}" \
82- CLUSTER_PRIVATEKEY="${BOOTSTRAP_PEER_PRIV_KEY}" \
83- exec ipfs-cluster-service daemon --upgrade
84- else
85- log "building the bootstrap address"
86- BOOTSTRAP_ADDR="/dns4/${SVC_NAME}-0.${SVC_NAME}/tcp/9096/ipfs/${BOOTSTRAP_PEER_ID}"
87- if [ -z "${BOOTSTRAP_ADDR}" ]; then
88- log "no bootstrap address found, exiting"
89- exit 1
90- fi
91- log "starting ipfs-cluster using the bootstrap address"
92- # Only ipfs user can get here
93- exec ipfs-cluster-service daemon --upgrade --bootstrap "${BOOTSTRAP_ADDR}" --leave
94- fi
95- }
96-
97- for op in "${@}"; do
98- case ${op} in
99- "debug")
100- log "💤 Sleeping indefinitely"
101- sleep infinity
102- log "✅ Done"
103- ;;
104- "run")
105- log "🏃 Running IPFS Cluster"
106- run_ipfs_cluster
107- log "✅ Done"
108- ;;
109- *)
110- log "😕 Operation '${op}' not defined"
111- exit 1
112- ;;
113- esac
114- done
115- `
116-
117- // TODO: dockerize kubo and move this script to the container
118- configureIpfs = `
119- #!/bin/sh
120- set -e
121- set -x
122- user=ipfs
123- # This is a custom entrypoint for k8s designed to run ipfs nodes in an appropriate
124- # setup for production scenarios.
125-
126- if [ -f /data/ipfs/config ]; then
127- if [ -f /data/ipfs/repo.lock ]; then
128- rm /data/ipfs/repo.lock
129- fi
130- exit 0
131- fi
132-
133- ipfs init --profile=badgerds,server
134- MYSELF=$(ipfs id -f="<id>")
135-
136- ipfs config Addresses.API /ip4/0.0.0.0/tcp/5001
137- ipfs config Addresses.Gateway /ip4/0.0.0.0/tcp/8080
138- ipfs config --json Swarm.ConnMgr.HighWater 2000
139- ipfs config --json Datastore.BloomFilterSize 1048576
140- ipfs config Datastore.StorageMax {{ .StorageMax }}GB
141- ipfs config --json Swarm.RelayClient '{{ .RelayClientJSON }}'
142- ipfs config --json Swarm.EnableHolePunching true
143- ipfs config --json Peering.Peers '{{ .PeersJSON }}'
144- ipfs config Datastore.StorageMax 100GB
145-
146- chown -R ipfs: /data/ipfs
147- `
148- )
149-
15022// configMapScripts Returns a mutate function which loads the given configMap with scripts that
15123// customize the startup of the IPFS containers depending on the values from the given IPFS cluster resource.
15224func (r * IpfsReconciler ) configMapScripts (
@@ -155,8 +27,8 @@ func (r *IpfsReconciler) configMapScripts(
15527 cm * corev1.ConfigMap ,
15628) (controllerutil.MutateFn , string ) {
15729 log := ctrllog .FromContext (ctx )
158- relayPeers := []* peer.AddrInfo {}
159- relayStatic := []* ma. Multiaddr {}
30+ relayPeers := []peer.AddrInfo {}
31+ relayStatic := []string {}
16032 for _ , relayName := range m .Status .CircuitRelays {
16133 relay := clusterv1alpha1.CircuitRelay {}
16234 relay .Name = relayName
@@ -171,19 +43,18 @@ func (r *IpfsReconciler) configMapScripts(
17143 continue
17244 }
17345 ai := relay .Status .AddrInfo .AddrInfo ()
174- relayPeers = append (relayPeers , ai )
46+ relayPeers = append (relayPeers , * ai )
17547 p2ppart , err := ma .NewMultiaddr ("/p2p/" + ai .ID .String ())
17648 if err != nil {
17749 log .Error (err , "could not create p2p component during configMapScripts" , "relay" , relayName )
17850 }
17951 for _ , addr := range ai .Addrs {
180- fullMa := addr .Encapsulate (p2ppart )
181- relayStatic = append (relayStatic , & fullMa )
52+ fullMa := addr .Encapsulate (p2ppart ). String ()
53+ relayStatic = append (relayStatic , fullMa )
18254 }
18355 }
18456
18557 cmName := "ipfs-cluster-scripts-" + m .Name
186- configureTmpl , _ := tmpl .New ("configureIpfs" ).Parse (configureIpfs )
18758 var storageMaxGB string
18859 parsed , err := resource .ParseQuantity (m .Spec .IpfsStorage )
18960 if err != nil {
@@ -201,29 +72,31 @@ func (r *IpfsReconciler) configMapScripts(
20172 storageMaxGB = strconv .Itoa (int (reducedSize ))
20273 }
20374
204- relayClientConfig := map [ string ] interface {} {
205- " Enabled" : true ,
206- " StaticRelays" : relayStatic ,
75+ relayConfig := config. RelayClient {
76+ Enabled : config . True ,
77+ StaticRelays : relayStatic ,
20778 }
208- relayClientConfigJSON , _ := json .Marshal (relayClientConfig )
209- peeringConfigJSON , _ := encjson .Marshal (relayPeers )
21079
211- configureOpts := configureIpfsOpts {
212- StorageMax : storageMaxGB ,
213- PeersJSON : string (peeringConfigJSON ),
214- RelayClientJSON : string (relayClientConfigJSON ),
80+ // get the config script
81+ configScript , err := scripts .CreateConfigureScript (
82+ storageMaxGB ,
83+ relayPeers ,
84+ relayConfig ,
85+ )
86+ if err != nil {
87+ return func () error {
88+ return err
89+ }, ""
21590 }
216- configureBuf := new (bytes.Buffer )
217- _ = configureTmpl .Execute (configureBuf , configureOpts )
21891
21992 expected := & corev1.ConfigMap {
22093 ObjectMeta : metav1.ObjectMeta {
22194 Name : cmName ,
22295 Namespace : m .Namespace ,
22396 },
22497 Data : map [string ]string {
225- "entrypoint.sh" : entrypoint ,
226- "configure-ipfs.sh" : configureBuf . String () ,
98+ "entrypoint.sh" : scripts . IPFSClusterEntrypoint ,
99+ "configure-ipfs.sh" : configScript ,
227100 },
228101 }
229102 expected .DeepCopyInto (cm )
0 commit comments