// Copyright 2024 Matthew Rich . All rights reserved. package main import ( "github.com/stretchr/testify/assert" "os" "os/exec" "testing" "errors" "log/slog" "net/http" "net/http/httptest" "fmt" "decl/internal/tempdir" "archive/tar" "io" "log" "bytes" ) var TempDir tempdir.Path = "testcli" func TestMain(m *testing.M) { err := TempDir.Create() if err != nil || TempDir == "" { slog.Error("Failed creating temp dir", "error", err) } rc := m.Run() TempDir.Remove() os.Exit(rc) } func TestCli(t *testing.T) { if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) { t.Skip("cli not built") } yaml, cliErr := exec.Command("./jx", "import", "--resource", "file://COPYRIGHT").Output() if cliErr != nil { slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr) } assert.Nil(t, cliErr) assert.NotEqual(t, "", string(yaml)) assert.Greater(t, len(yaml), 0) } func TestCliHTTPSource(t *testing.T) { if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) { t.Skip("cli not built") } ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, ` resources: - type: file attributes: path: foo.txt owner: nobody group: nobody mode: 0644 content: | test file content state: present `) })) defer ts.Close() yaml, cliErr := exec.Command("./jx", "import", "--resource", ts.URL).Output() if cliErr != nil { slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr) } assert.Nil(t, cliErr) assert.NotEqual(t, "", string(yaml)) assert.Greater(t, len(yaml), 0) } func TestCliConfigSource(t *testing.T) { if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) { t.Skip("cli not built") } configYaml := ` configurations: - name: myhttpconnection values: http_user: foo http_pass: bar ` configPath := fmt.Sprintf("%s/testconfig.jx.yaml", TempDir) f, err := os.Create(configPath) assert.Nil(t, err) defer f.Close() _, writeErr := f.Write([]byte(configYaml)) assert.Nil(t, writeErr) yaml, cliErr := exec.Command("./jx", "import", "--config", configPath, "--resource", "file://COPYRIGHT").Output() if cliErr != nil { slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr) } assert.Nil(t, cliErr) slog.Info("TestConfigSource", "yaml", yaml) } func TestCliConfigCommand(t *testing.T) { if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) { t.Skip("cli not built") } yaml, cliErr := exec.Command("./jx", "config", "file://examples/config/file.jx.yaml").Output() if cliErr != nil { slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr) } assert.Nil(t, cliErr) slog.Info("TestConfigCommand", "yaml", yaml) assert.NotEqual(t, "", string(yaml)) assert.Greater(t, len(yaml), 0) } func TestCliImportPackageCommand(t *testing.T) { if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) { t.Skip("cli not built") } yaml, cliErr := exec.Command("./jx", "import", "package://").Output() if cliErr != nil { slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr) } assert.Nil(t, cliErr) assert.NotEqual(t, "", string(yaml)) assert.Greater(t, len(yaml), 0) } func TestCliExportTar(t *testing.T) { if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) { t.Skip("cli not built") } assert.Nil(t, TempDir.Mkdir("tar", 0755)) assert.Nil(t, TempDir.CreateFile("tar/foo", "data")) assert.Nil(t, TempDir.CreateFile("tar/bar", "data")) cmdArgs := []string{"import", "--output", "tar://-", fmt.Sprintf("file://%s/tar", TempDir)} slog.Info("TestCliExportTar()", "cmd", cmdArgs) cmd := exec.Command("./jx", cmdArgs...) slog.Info("TestCliExportTar()", "cmd", cmd) stderr, errerr := cmd.StderrPipe() assert.Nil(t, errerr) stdout, outerr := cmd.StdoutPipe() assert.Nil(t, outerr) assert.Nil(t, cmd.Start()) errOutput, _ := io.ReadAll(stderr) tarData, _ := io.ReadAll(stdout) assert.Nil(t, cmd.Wait()) slog.Info("TestCliExportTar()", "stderr", errOutput) assert.Greater(t, len(tarData), 0) tr := tar.NewReader(bytes.NewBuffer(tarData)) files := []string{fmt.Sprintf("%s/tar/foo", TempDir), fmt.Sprintf("%s/tar/bar", TempDir)} for { hdr, err := tr.Next() if err == io.EOF { break } if err != nil { log.Fatal(err) } assert.Contains(t, files, hdr.Name) contents, err := io.ReadAll(tr) assert.Nil(t, err) assert.Equal(t, []byte("data"), contents) } } func TestResourcesRead(t *testing.T) { if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) { t.Skip("cli not built") } server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { defer req.Body.Close() assert.Equal(t, req.URL.String(), "/resource/user") _, err := io.ReadAll(req.Body) assert.Nil(t, err) userdecl := []byte(` type: "user" attributes: name: "foo" gecos: "foo user" `) _, writeErr := rw.Write(userdecl) assert.Nil(t, writeErr) })) defer server.Close() assert.Nil(t, TempDir.CreateFile("testread", "data")) resources := fmt.Sprintf(` resources: - type: file transition: read attributes: path: %s - type: user transition: read attributes: name: nobody - type: group transition: read attributes: name: wheel - type: container transition: read attributes: name: builder - type: container-network transition: read attributes: name: default - type: container-image transition: read attributes: name: nginx:latest - type: http transition: read attributes: endpoint: %s/resource/user - type: route transition: read attributes: to: 0.0.0.0 gateway: 172.17.0.1 interface: eth0 proto: static scope: global rtid: all routetype: local metric: 100 `, TempDir.FilePath("testread"), server.URL) assert.Nil(t, TempDir.CreateFile("resources.jx.yaml", resources)) yaml, cliErr := exec.Command("./jx", "apply", TempDir.FilePath("resources.jx.yaml")).Output() if cliErr != nil { slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr) } assert.Nil(t, cliErr) assert.NotEqual(t, "", string(yaml)) assert.Greater(t, len(yaml), 0) } func TestFailedResources(t *testing.T) { if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) { t.Skip("cli not built") } os.Unsetenv("JX_DEBUG") resources := ` resources: - type: package transition: create attributes: name: foobarbaz ` assert.Nil(t, TempDir.CreateFile("err.jx.yaml", resources)) yaml, cliErr := exec.Command("./jx", "apply", TempDir.FilePath("err.jx.yaml")).Output() if cliErr != nil { slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr) } assert.NotNil(t, cliErr) assert.NotEqual(t, "", string(yaml)) assert.Contains(t, string(cliErr.(*exec.ExitError).Stderr), "Document errors: 1") }