~egtann/inv2config

95bfefad38964c16b14a70c219135241ac77675e — Evan Tann 9 months ago 3230677
fix port concat bug
1 files changed, 45 insertions(+), 24 deletions(-)

M main.go
M main.go => main.go +45 -24
@@ 7,6 7,8 @@ import (
	"fmt"
	"io/ioutil"
	"os"
	"sort"
	"strings"

	"git.sr.ht/~egtann/up"
)


@@ 16,7 18,7 @@ func main() {
	srpOut, err := run()
	fmt.Printf(srpOut)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		fmt.Fprintln(os.Stderr, fmt.Sprintf("\nerror: %v", err))
		os.Exit(1)
	}
}


@@ 29,6 31,8 @@ func run() (string, error) {
	)
	flag.Parse()

	// Parse our SRP config file, but retain the original bytes in case any
	// error occurs
	srpByt, err := ioutil.ReadFile(*srpFile)
	if err != nil {
		return "", fmt.Errorf("read srp config: %w", err)


@@ 44,26 48,40 @@ func run() (string, error) {
		return origSRP, fmt.Errorf("parse inventory: %w", err)
	}

	// Gee willikers, Batman, this is O(N^3)
	// Convert our inventory into a data structure for fast lookups
	serviceToIPs := map[string][]string{}
	for ip, serviceNames := range inventory {
	middle:
		for _, name := range serviceNames {
			for _, backend := range conf.Services {
				if backend.Service != name {
					continue
				}
				if ip == "" {
					continue
				}
				ipPort := fmt.Sprintf("%s:%d", ip, backend.Port)
				if backend.Port == 0 {
					ipPort = ip
				}
				backend.Backends = append(backend.Backends, ipPort)
				conf.Services[name] = backend
				break middle
			serviceToIPs[name] = append(serviceToIPs[name], ip)
		}
	}

	// Update ip:port combos for each backend
	missingServices := serviceMap{}
	for _, backend := range conf.Services {
		service := backend.Service
		if service == "" {
			continue
		}
		ips, ok := serviceToIPs[service]
		if !ok {
			missingServices[service] = struct{}{}
			continue
		}
		ips = append([]string{}, ips...)
		if backend.Port > 0 {
			for i, ip := range ips {
				ips[i] = fmt.Sprintf("%s:%d", ip, backend.Port)
			}
		}
		sort.Strings(ips)
		backend.Backends = append([]string{}, ips...)
		conf.Services[service] = backend
	}
	if len(missingServices) > 0 {
		err := fmt.Errorf("services undefined in inventory: %v",
			missingServices)
		return origSRP, err
	}

	buf := &bytes.Buffer{}


@@ 72,13 90,6 @@ func run() (string, error) {
	if err := enc.Encode(conf); err != nil {
		return origSRP, fmt.Errorf("encode config: %w", err)
	}

	// TODO(egtann) output the original config via stdout if any error
	// happens.
	//
	// TODO(egtann) on success, output the config formatted for human
	// editing (i.e. prettify)

	return string(buf.Bytes()), nil
}



@@ 95,3 106,13 @@ func parseInventory(filename string) (up.Inventory, error) {
	}
	return inv, nil
}

type serviceMap map[string]struct{}

func (s serviceMap) String() string {
	out := make([]string, 0, len(s))
	for srv := range s {
		out = append(out, srv)
	}
	return strings.Join(out, ", ")
}