env-manager: dynamically generate cidr for new env (#85)
* env-manager: allocate env cidrs dynamically
* fix: net.IP to netip.Addr conversion
* bootstrapper: generate empty env-cidrs.yaml
* fix: net.IP to netip.Addr conversion for IP pool
* infra: expose provided startIP subnet via tailscale proxy
* headscale: pass private network ip subnet to expose to api service
* dns: make ingress IP configurable
---------
Co-authored-by: Giorgi Lekveishvili <lekva@gl-mbp-m1-max.local>
diff --git a/core/installer/welcome/env.go b/core/installer/welcome/env.go
index 10a2ade..5436702 100644
--- a/core/installer/welcome/env.go
+++ b/core/installer/welcome/env.go
@@ -11,6 +11,7 @@
"log"
"net"
"net/http"
+ "net/netip"
"strings"
"github.com/gorilla/mux"
@@ -293,6 +294,10 @@
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
+ if err := s.repo.CommitAndPush(fmt.Sprintf("Allocate CIDR for %s", req.Name)); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
// if err := s.acceptInvitation(req.SecretToken); err != nil {
// http.Error(w, err.Error(), http.StatusInternalServerError)
// return
@@ -303,6 +308,27 @@
} else {
req.Name = name
}
+ var cidrs installer.EnvCIDRs
+ cidrsR, err := s.repo.Reader("env-cidrs.yaml")
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ defer cidrsR.Close()
+ if err := installer.ReadYaml(cidrsR, &cidrs); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ startIP, err := findNextStartIP(cidrs)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ cidrs = append(cidrs, installer.EnvCIDR{req.Name, startIP})
+ if err := s.repo.WriteYaml("env-cidrs.yaml", cidrs); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
t, dns := tasks.NewCreateEnvTask(
tasks.Env{
PCloudEnvName: env.Name,
@@ -315,6 +341,7 @@
net.ParseIP("135.181.48.180"),
net.ParseIP("65.108.39.172"),
},
+ startIP,
s.nsCreator,
s.repo,
)
@@ -331,3 +358,33 @@
go t.Start()
http.Redirect(w, r, fmt.Sprintf("/env/%s", key), http.StatusSeeOther)
}
+
+func findNextStartIP(cidrs installer.EnvCIDRs) (net.IP, error) {
+ m, err := netip.ParseAddr("10.0.0.0")
+ if err != nil {
+ return nil, err
+ }
+ for _, cidr := range cidrs {
+ i, err := netip.ParseAddr(cidr.IP.String())
+ if err != nil {
+ return nil, err
+ }
+ if i.Compare(m) > 0 {
+ m = i
+ }
+ }
+ sl := m.AsSlice()
+ sl[2]++
+ if sl[2] == 0b11111111 {
+ sl[2] = 0
+ sl[1]++
+ }
+ if sl[1] == 0b11111111 {
+ return nil, fmt.Errorf("Can not allocate")
+ }
+ ret, ok := netip.AddrFromSlice(sl)
+ if !ok {
+ return nil, fmt.Errorf("Must not reach")
+ }
+ return net.ParseIP(ret.String()), nil
+}