installer: fix how collection of in memory app configs is created (#74)

Was allocating non empty slice before, which followed by appends
would leave nil-s at the beginning of the slice.

Co-authored-by: Giorgi Lekveishvili <lekva@gl-mbp-m1-max.local>
diff --git a/core/installer/app_test.go b/core/installer/app_test.go
index d43809c..6162299 100644
--- a/core/installer/app_test.go
+++ b/core/installer/app_test.go
@@ -1,296 +1,16 @@
 package installer
 
 import (
-	"bytes"
-	"context"
-	_ "embed"
-	"encoding/json"
-	"fmt"
-	"io"
-	"net/http"
-	"strings"
 	"testing"
-	"time"
-
-	"cuelang.org/go/cue"
-	"cuelang.org/go/cue/cuecontext"
-	fluxcd "github.com/fluxcd/source-controller/api/v1beta2"
-	"helm.sh/helm/v3/pkg/registry"
-	// "github.com/go-git/go-billy/v5/memfs"
-	"github.com/go-git/go-billy/v5/osfs"
-	"helm.sh/helm/v3/pkg/action"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/apimachinery/pkg/runtime/schema"
-	"k8s.io/client-go/dynamic"
-	"k8s.io/client-go/rest"
-	"k8s.io/client-go/tools/clientcmd"
 )
 
-//go:embed values-tmpl/rpuppy.cue
-var rpuppyConfig []byte
-
-type ContainerImage struct {
-	Repository string
-	Tag        string
-	PullPolicy string
-}
-
-type Chart struct {
-	Source ChartSource
-	Chart  string
-}
-
-type ChartSource struct {
-	Kind    string
-	Address string
-}
-
-type ApplicationConfig struct {
-	Images map[string]ContainerImage
-	Charts map[string]Chart
-}
-
-type client struct {
-	clientset dynamic.Interface
-}
-
-func (c *client) CreateHelmChart(chart fluxcd.HelmChart) error {
-	var buf bytes.Buffer
-	if err := json.NewEncoder(&buf).Encode(chart); err != nil {
-		return nil
-	}
-	var u unstructured.Unstructured
-	if err := json.NewDecoder(&buf).Decode(&u.Object); err != nil {
-		return err
-	}
-	_, err := c.clientset.Resource(schema.GroupVersionResource{Group: fluxcd.GroupVersion.Group, Version: fluxcd.GroupVersion.Version, Resource: "helmcharts"}).Namespace(chart.Namespace).Create(context.TODO(), &u, metav1.CreateOptions{})
-	return err
-}
-
-func NewClient(kubeconfig string) (*client, error) {
-	if kubeconfig == "" {
-		config, err := rest.InClusterConfig()
-		if err != nil {
-			return nil, err
-		}
-		c, err := dynamic.NewForConfig(config)
-		if err != nil {
-			return nil, err
-		}
-		return &client{c}, nil
-
-	} else {
-		config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
-		if err != nil {
-			return nil, err
-		}
-		c, err := dynamic.NewForConfig(config)
-		if err != nil {
-			return nil, err
-		}
-		return &client{c}, nil
-	}
-}
-
-const networkSchema = `
-#Network: {
-	IngressClass: string
-	CertificateIssuer: string
-	Domain: string
-}
-
-value: %s
-
-valid: #Network & value
-`
-
-type StringFormatter struct {
-	s strings.Builder
-}
-
-func (f *StringFormatter) Write(b []byte) (n int, err error) {
-	return f.s.Write(b)
-}
-
-func (f *StringFormatter) Width() (wid int, ok bool) {
-	return 4, true
-}
-
-func (f *StringFormatter) Precision() (prec int, ok bool) {
-	return 4, true
-}
-
-func (f *StringFormatter) Flag(c int) bool {
-	return false
-}
-
-func IsNetwork(v cue.Value) bool {
-	if v.Value().Kind() != cue.StructKind {
-		return false
-	}
-	value := fmt.Sprintf("%#v", v)
-	s := fmt.Sprintf(networkSchema, value)
-	c := cuecontext.New()
-	u := c.CompileString(s)
-	return u.Err() == nil && u.Validate() == nil
-}
-
-func PrintSchema(v cue.Value) {
-	f, _ := v.Fields()
-	for f.Next() {
-		fmt.Printf("%s\n", f.Selector())
-		if IsNetwork(f.Value()) {
-			fmt.Println("network")
-		}
-		PrintSchema(f.Value())
-	}
-}
-
-func TestInput(t *testing.T) {
-	c := cuecontext.New()
-	cfg := c.CompileBytes(rpuppyConfig)
-	input := c.CompileString(`
-global: {
-  id: "foo"
-}
-input: {
-  network: {
-    name: "public"
-    ingressClass: "dodo-ingress-public"
-    certificateIssuer: "rpuppu-public"
-    domain: "lekva.me"
-  }
-  subdomain: "rpuppy"
-}
-`)
-	if cfg.Err() != nil {
-		panic(cfg.Err())
-	}
-	if err := cfg.Validate(); err != nil {
-		panic(err)
-	}
-	PrintSchema(cfg.Eval().LookupPath(cue.ParsePath("input")))
-	out := cfg.Unify(input)
-	if out.Err() != nil {
-		panic(out.Err())
-	}
-	if err := out.Validate(); err != nil {
-		panic(err)
-	}
-	fmt.Printf("%#v\n", out)
-	e := out.Eval()
-	if e.Err() != nil {
-		panic(out.Err())
-	}
-	if err := e.Validate(); err != nil {
-		panic(err)
-	}
-	fmt.Printf("%#v\n", e)
-	fmt.Println(e.IsConcrete())
-}
-
-func TestParseApplicationConfig(t *testing.T) {
-	return
-	var r cue.Runtime
-	i, err := r.Compile("rpuppy", rpuppyConfig)
+func TestHeadscaleUser(t *testing.T) {
+	r := NewInMemoryAppRepository(CreateAllApps())
+	a, err := r.Find("headscale-user")
 	if err != nil {
-		panic(err)
+		t.Fatal(err)
 	}
-	var cfg ApplicationConfig
-	if err := i.Value().Decode(&cfg); err != nil {
-		panic(err)
+	if a == nil {
+		t.Fatal("returned app is nil")
 	}
-	fmt.Printf("%+v\n", cfg)
-	_, err = NewClient("/Users/lekva/dev/src/pcloud/priv/kubeconfig-hetzner")
-	if err != nil {
-		panic(err)
-	}
-
-	for name, c := range cfg.Charts {
-		chart := fluxcd.HelmChart{
-			TypeMeta: metav1.TypeMeta{
-				APIVersion: fluxcd.GroupVersion.String(),
-				Kind:       "HelmChart",
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      name,
-				Namespace: "dodo",
-			},
-			Spec: fluxcd.HelmChartSpec{
-				Chart: c.Chart,
-				SourceRef: fluxcd.LocalHelmChartSourceReference{
-					Kind: c.Source.Kind,
-					Name: c.Source.Address,
-				},
-				Interval: metav1.Duration{time.Hour},
-			},
-		}
-		fmt.Printf("%+v\n", chart)
-		// if err := client.CreateHelmChart(chart); err != nil {
-		// 	panic(err)
-		// }
-	}
-}
-
-type downloader struct {
-	client *http.Client
-}
-
-func NewDownloader() *downloader {
-	return &downloader{
-		client: http.DefaultClient,
-	}
-}
-
-func (d *downloader) Download(addr string, out io.Writer) error {
-	resp, err := d.client.Get(addr)
-	if err != nil {
-		return err
-	}
-	if _, err := io.Copy(out, resp.Body); err != nil {
-		return err
-	}
-	return nil
-}
-
-func TestDownload(t *testing.T) {
-	return
-	// fs := memfs.New()
-	fs := osfs.New("/tmp")
-	func() {
-		f, err := fs.Create("/chart")
-		if err != nil {
-			panic(err)
-		}
-		defer f.Close()
-		d := NewDownloader()
-		if err := d.Download("http://localhost:9090/helmchart/dodo/rpuppy/rpuppy-0.0.1.tgz", f); err != nil {
-			panic(err)
-		}
-	}()
-	client, err := registry.NewClient()
-	if err != nil {
-		panic(err)
-	}
-	if err := client.Login("https://harbor.t46.lekva.me", registry.LoginOptBasicAuth("admin", "Harbor12345")); err != nil {
-		panic(err)
-	}
-	defer client.Logout("https://harbor.t46.lekva.me")
-	push := action.NewPushWithOpts(action.WithPushConfig(&action.Configuration{
-		RegistryClient: client,
-	}))
-	fmt.Printf("%+v\n", push)
-	res, err := push.Run("/tmp/chart", "oci://harbor.t46.lekva.me/library/charts")
-	fmt.Println(res)
-	if err != nil {
-		panic(err)
-	}
-	// cfg, err := ActionConfigFactory{"/Users/lekva/dev/src/pcloud/priv/kubeconfig-hetzner"}.New("")
-	// installer := action.NewInstall(config)
-	// installer.Namespace = env.Name
-	// installer.ReleaseName = "metallb-ns"
-	// installer.Wait = true
-	// installer.WaitForJobs = true
-
 }