Skip to content

Commit

Permalink
Merge branch 'main' into 1124-package-preview-prompt-variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Racer159 authored Jun 22, 2023
2 parents 631a695 + a6cf75f commit c3739fb
Show file tree
Hide file tree
Showing 35 changed files with 669 additions and 185 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test-ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ jobs:
path: "~/.cache/ms-playwright/"
key: ${{ runner.os }}-browsers

- name: Ensure playwright is installed
run: npx playwright install
- name: Ensure playright is installed
run: npx --prefix src/ui playwright install

- name: Run UI tests
run: make test-ui
Expand All @@ -60,5 +60,5 @@ jobs:
if: always()
with:
name: playwright-report
path: playwright-report/
path: src/ui/playwright-report/
retention-days: 30
11 changes: 8 additions & 3 deletions src/cmd/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ var packageListCmd = &cobra.Command{
Short: lang.CmdPackageListShort,
Run: func(cmd *cobra.Command, args []string) {
// Get all the deployed packages
deployedZarfPackages, err := cluster.NewClusterOrDie().GetDeployedZarfPackages()
if err != nil {
message.Fatalf(err, lang.CmdPackageListNoPackageWarn)
deployedZarfPackages, errs := cluster.NewClusterOrDie().GetDeployedZarfPackages()
if len(errs) > 0 && len(deployedZarfPackages) == 0 {
message.Fatalf(errs, lang.CmdPackageListNoPackageWarn)
}

// Populate a pterm table of all the deployed packages
Expand All @@ -149,6 +149,11 @@ var packageListCmd = &cobra.Command{

// Print out the table for the user
_ = pterm.DefaultTable.WithHasHeader().WithData(packageTable).Render()

// Print out any unmarshalling errors
if len(errs) > 0 {
message.Fatalf(errs, lang.CmdPackageListUnmarshalErr)
}
},
}

Expand Down
1 change: 1 addition & 0 deletions src/config/lang/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ const (

CmdPackageListShort = "Lists out all of the packages that have been deployed to the cluster (runs offline)"
CmdPackageListNoPackageWarn = "Unable to get the packages deployed to the cluster"
CmdPackageListUnmarshalErr = "Unable to read all of the packages deployed to the cluster"

CmdPackageCreateFlagConfirm = "Confirm package creation without prompting"
CmdPackageCreateFlagSet = "Specify package variables to set on the command line (KEY=value)"
Expand Down
65 changes: 47 additions & 18 deletions src/internal/api/packages/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ package packages

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
Expand Down Expand Up @@ -44,7 +46,7 @@ func DeployPackage(w http.ResponseWriter, r *http.Request) {
defer pkgClient.ClearTempPaths()

if err := pkgClient.Deploy(); err != nil {
message.ErrorWebf(err, w, "Unable to deploy the zarf package to the cluster")
message.ErrorWebf(err, w, err.Error())
return
}

Expand All @@ -59,33 +61,60 @@ func StreamDeployPackage(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Connection", "keep-alive")

pr, pw, _ := os.Pipe()

pterm.SetDefaultOutput(pw)
pterm.DisableStyling()
logStream := io.MultiWriter(message.LogWriter, pw)
pterm.SetDefaultOutput(logStream)

scanner := bufio.NewScanner(pr)
scanner.Split(splitStreamLines)
done := r.Context().Done()

for {
// Loop through the scanner and send each line to the stream
for scanner.Scan() {
select {
// If the context is done, reset the output and return
case (<-done):
pterm.SetDefaultOutput(os.Stderr)
pterm.EnableStyling()
pterm.SetDefaultOutput(message.LogWriter)
return
default:
n := scanner.Scan()
if err := scanner.Err(); err != nil {
message.ErrorWebf(err, w, "Error reading stdout: %v", err)
err := scanner.Err()
if err != nil {
message.ErrorWebf(err, w, "Unable to read the stream")
return
}
if n {
// TODO: dig in to alternatives to trim
// Some output is not sent unless trimmed
// Specifically the output from the loading spinner.
trimmed := strings.TrimSpace(scanner.Text())
fmt.Fprintf(w, "data: %s\n\n", trimmed)
w.(http.Flusher).Flush()
}
line := scanner.Text()

// Clean up the line and send it to the stream
trimmed := strings.TrimSpace(line)

fmt.Fprintf(w, "data: %s\n\n", trimmed)
w.(http.Flusher).Flush()
}
}
}

// Splits scanner lines on '\n', '\r', and '\r\n' line endings to ensure the progress and spinner lines show up correctly
func splitStreamLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
// If data ends with '\n', return the line without '\n' or '\r\n'
if i := bytes.IndexByte(data, '\n'); i >= 0 {
// Drop the preceding carriage return if it exists
if i > 0 && data[i-1] == '\r' {
return i + 1, data[:i-1], nil
}

return i + 1, data[:i], nil
}
// if data ends with '\r', return the line without '\r'
if i := bytes.IndexByte(data, '\r'); i >= 0 {
return i + 1, data[:i], nil
}

// If we're at EOF and we have a final non-terminated line. Return it.
if atEOF {
return len(data), data, nil
}

return 0, nil, nil
}
5 changes: 3 additions & 2 deletions src/internal/api/packages/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ func ListDeployedPackages(w http.ResponseWriter, _ *http.Request) {
return
}

deployedPackages, err := c.GetDeployedZarfPackages()
if err != nil {
deployedPackages, errs := c.GetDeployedZarfPackages()
// TODO #1312: Handle errors where some deployedPackages were able to be parsed
if len(errs) > 0 && len(deployedPackages) == 0 {
message.ErrorWebf(err, w, "Unable to get a list of the deployed Zarf packages")
return
}
Expand Down
19 changes: 11 additions & 8 deletions src/internal/cluster/zarf.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package cluster
import (
"context"
"encoding/json"
"fmt"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/message"
Expand All @@ -18,29 +19,31 @@ import (

// GetDeployedZarfPackages gets metadata information about packages that have been deployed to the cluster.
// We determine what packages have been deployed to the cluster by looking for specific secrets in the Zarf namespace.
func (c *Cluster) GetDeployedZarfPackages() ([]types.DeployedPackage, error) {
// Returns a list of DeployedPackage structs and a list of errors.
func (c *Cluster) GetDeployedZarfPackages() ([]types.DeployedPackage, []error) {
var deployedPackages = []types.DeployedPackage{}

var errorList []error
// Get the secrets that describe the deployed packages
secrets, err := c.Kube.GetSecretsWithLabel(ZarfNamespaceName, ZarfPackageInfoLabel)
if err != nil {
return deployedPackages, err
return deployedPackages, append(errorList, err)
}

// Process the k8s secret into our internal structs
for _, secret := range secrets.Items {
var deployedPackage types.DeployedPackage
err := json.Unmarshal(secret.Data["data"], &deployedPackage)
// add the error to the error list
if err != nil {
message.Warnf("Unable to unmarshal package secret")

return deployedPackages, err
errorList = append(errorList, fmt.Errorf("unable to unmarshal the secret %s/%s", secret.Namespace, secret.Name))
} else {
deployedPackages = append(deployedPackages, deployedPackage)
}

deployedPackages = append(deployedPackages, deployedPackage)
}

return deployedPackages, nil
// TODO: If we move this function out of `internal` we should return a more standard singular error.
return deployedPackages, errorList
}

// GetDeployedPackage gets the metadata information about the package name provided (if it exists in the cluster).
Expand Down
11 changes: 7 additions & 4 deletions src/pkg/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ var NoProgress bool
// RuleLine creates a line of ━ as wide as the terminal
var RuleLine = strings.Repeat("━", TermWidth)

// LogWriter is the stream to write logs to.
var LogWriter io.Writer = os.Stderr

var logLevel = InfoLevel

// Write logs to stderr and a buffer for logFile generation.
Expand Down Expand Up @@ -83,16 +86,16 @@ func UseLogFile() {
var err error
if logFile != nil {
// Use the existing log file if logFile is set
logStream := io.MultiWriter(os.Stderr, logFile)
pterm.SetDefaultOutput(logStream)
LogWriter = io.MultiWriter(os.Stderr, logFile)
pterm.SetDefaultOutput(LogWriter)
} else {
// Try to create a temp log file if one hasn't been made already
if logFile, err = os.CreateTemp("", fmt.Sprintf("zarf-%s-*.log", ts)); err != nil {
WarnErr(err, "Error saving a log file to a temporary directory")
} else {
useLogFile = true
logStream := io.MultiWriter(os.Stderr, logFile)
pterm.SetDefaultOutput(logStream)
LogWriter = io.MultiWriter(os.Stderr, logFile)
pterm.SetDefaultOutput(LogWriter)
message := fmt.Sprintf("Saving log file to %s", logFile.Name())
Note(message)
}
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/02_initialize_cluster.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,19 +111,19 @@ test.describe('initialize a zarf cluster', () => {
const stepperItems = page.locator('.stepper-vertical .step-icon');

// deploy zarf-injector
await expect(stepperItems.nth(0)).toHaveClass(/success/, {
await expect(stepperItems.nth(0)).not.toHaveClass(/error/, {
timeout: 45000,
});
// deploy zarf-seed-registry
await expect(stepperItems.nth(1)).toHaveClass(/success/, {
await expect(stepperItems.nth(1)).not.toHaveClass(/error/, {
timeout: 45000,
});
// deploy zarf-registry
await expect(stepperItems.nth(2)).toHaveClass(/success/, {
await expect(stepperItems.nth(2)).not.toHaveClass(/error/, {
timeout: 45000,
});
// deploy zarf-agent
await expect(stepperItems.nth(3)).toHaveClass(/success/, {
await expect(stepperItems.nth(3)).not.toHaveClass(/error/, {
timeout: 45000,
});

Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/03_deploy_non_init.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ const getToReview = async (page) => {

test('deploy the dos-games package @post-init', async ({ page }) => {
await getToReview(page);

// Validate that the SBOM has been loaded
const sbomInfo = await page.waitForSelector('#sbom-info', { timeout: 20000 });
expect(await sbomInfo.innerText()).toMatch(/[0-9]+ artifacts to be reviewed/);

await page.getByRole('link', { name: 'deploy package' }).click();
await page.waitForURL('/packages/dos-games/deploy', { waitUntil: 'networkidle' });

Expand Down
1 change: 1 addition & 0 deletions src/ui/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ node_modules
pnpm-lock.yaml
package-lock.json
yarn.lock
lib/api-types.ts
8 changes: 4 additions & 4 deletions src/ui/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ module.exports = {
ignorePatterns: ['*.cjs'],
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
settings: {
'svelte3/typescript': () => require('typescript')
'svelte3/typescript': () => require('typescript'),
},
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020
ecmaVersion: 2020,
},
env: {
browser: true,
es2017: true,
node: true
}
node: true,
},
};
2 changes: 1 addition & 1 deletion src/ui/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ node_modules
.env
.env.*
!.env.example
/src/ui/lib/api-types.ts
lib/api-types.ts

# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
let open: boolean;
let currentWindow: Window;
let selectedConnection = '';
let errMessage: string = '';
let errMessage = '';
const connections: string[] = Object.keys(pkg.connectStrings || {}) || [];
const listSSX: SSX = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@
import RemoveDeployedPackageDialog from './remove-deployed-package-dialog.svelte';
import ConnectDeployedPackageDialog from './connect-deployed-package-dialog.svelte';
import DisconnectDeployedPackageDialog from './disconnect-deployed-package-dialog.svelte';
import YamlDrawer from '../yaml-drawer.svelte';
export let pkg: DeployedPackage;
let anchorRef: HTMLButtonElement;
let toggleRemoveDialog: () => void;
let toggleConnectDialog: () => void;
let toggleDisconnectDialog: () => void;
let toggleYamlDrawer: () => void;
let updateLink = '';
let toggled = false;
const menuSSX: SSX = {
$self: {
'position': 'fixed',
position: 'fixed',
'& .list-item-adornment': { color: 'var(--text-secondary-on-dark)' },
'& .divider': { height: '1px', boxShadow: 'inset 0px -1px 0px rgba(255,255,255,0.12)' },
},
Expand Down Expand Up @@ -65,37 +67,33 @@
<ListItemAdornment slot="leading" class="material-symbols-outlined">
signal_disconnected
</ListItemAdornment>
<Typography>
Disconnect...
</Typography>
<Typography>Disconnect...</Typography>
</ListItem>
{/if}
<ListItem on:click={toggleConnectDialog}>
<ListItemAdornment slot="leading" class="material-symbols-outlined">
private_connectivity
</ListItemAdornment>
<Typography>
Connect...
</Typography>
<Typography>Connect...</Typography>
</ListItem>
<ListItem on:click={() => goto(updateLink)}>
<ListItemAdornment slot="leading" class="material-symbols-outlined">cached</ListItemAdornment>
<Typography>Update Package...</Typography>
</ListItem>
<div class="divider" />
<ListItem on:click={toggleYamlDrawer}>
<ListItemAdornment slot="leading" class="material-symbols-outlined">
cached
code_blocks
</ListItemAdornment>
<Typography>
Update Package...
</Typography>
<Typography>View Code</Typography>
</ListItem>
<div class="divider" />
<ListItem on:click={toggleRemoveDialog}>
<ListItemAdornment slot="leading" class="material-symbols-outlined">
delete
</ListItemAdornment>
<Typography>
Remove...
</Typography>
<ListItemAdornment slot="leading" class="material-symbols-outlined">delete</ListItemAdornment>
<Typography>Remove...</Typography>
</ListItem>
</Menu>
<DisconnectDeployedPackageDialog {pkg} bind:toggleDialog={toggleDisconnectDialog} />
<ConnectDeployedPackageDialog {pkg} bind:toggleDialog={toggleConnectDialog} />
<RemoveDeployedPackageDialog {pkg} bind:toggleDialog={toggleRemoveDialog} />
<YamlDrawer code={pkg.data} bind:toggleDrawer={toggleYamlDrawer} />
Loading

0 comments on commit c3739fb

Please sign in to comment.