constellation/internal/api/versionsapi/cli/latest.go
Otto Bittner 97dc15b1d1 staticupload: correctly set invalidation timeout
Previously the timeout was not set in the client's constructor, thus the
zero value was used. The client did not wait for invalidation.
To prevent this in the future a warning is logged if wait is disabled.

Co-authored-by: Daniel Weiße <dw@edgeless.systems>
2023-09-04 11:20:13 +02:00

151 lines
3.6 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package main
import (
"encoding/json"
"errors"
"fmt"
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
"github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/spf13/cobra"
"go.uber.org/zap/zapcore"
)
func newLatestCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "latest",
Short: "Find latest version",
Long: "Find latest version of a ref/stream. The returned version is in short format, if --json flag is not set.",
RunE: runLatest,
Args: cobra.ExactArgs(0),
}
cmd.Flags().String("ref", "-", "Ref to query")
cmd.Flags().String("stream", "stable", "Stream to query")
cmd.Flags().Bool("json", false, "Whether to output the result as JSON")
return cmd
}
func runLatest(cmd *cobra.Command, _ []string) (retErr error) {
flags, err := parseLatestFlags(cmd)
if err != nil {
return err
}
log := logger.New(logger.PlainLog, flags.logLevel)
log.Debugf("Parsed flags: %+v", flags)
log.Debugf("Validating flags")
if err := flags.validate(); err != nil {
return err
}
log.Debugf("Creating versions API client")
client, clientClose, err := versionsapi.NewReadOnlyClient(cmd.Context(), flags.region, flags.bucket, flags.distributionID, log)
if err != nil {
return fmt.Errorf("creating client: %w", err)
}
defer func() {
err := clientClose(cmd.Context())
if err != nil {
retErr = errors.Join(retErr, fmt.Errorf("failed to invalidate cache: %w", err))
}
}()
log.Debugf("Requesting latest version")
latest := versionsapi.Latest{
Ref: flags.ref,
Stream: flags.stream,
Kind: versionsapi.VersionKindImage,
}
latest, err = client.FetchVersionLatest(cmd.Context(), latest)
if err != nil {
return fmt.Errorf("fetching latest version: %w", err)
}
if flags.json {
out, err := json.MarshalIndent(latest, "", " ")
if err != nil {
return fmt.Errorf("marshaling JSON: %w", err)
}
fmt.Fprintln(cmd.OutOrStdout(), string(out))
return nil
}
fmt.Fprintln(cmd.OutOrStdout(), latest.ShortPath())
return nil
}
type latestFlags struct {
ref string
stream string
json bool
region string
bucket string
distributionID string
logLevel zapcore.Level
}
func (l *latestFlags) validate() error {
if err := versionsapi.ValidateRef(l.ref); err != nil {
return fmt.Errorf("invalid ref: %w", err)
}
if err := versionsapi.ValidateStream(l.ref, l.stream); err != nil {
return fmt.Errorf("invalid stream: %w", err)
}
return nil
}
func parseLatestFlags(cmd *cobra.Command) (latestFlags, error) {
ref, err := cmd.Flags().GetString("ref")
if err != nil {
return latestFlags{}, err
}
ref = versionsapi.CanonicalizeRef(ref)
stream, err := cmd.Flags().GetString("stream")
if err != nil {
return latestFlags{}, err
}
json, err := cmd.Flags().GetBool("json")
if err != nil {
return latestFlags{}, err
}
region, err := cmd.Flags().GetString("region")
if err != nil {
return latestFlags{}, err
}
bucket, err := cmd.Flags().GetString("bucket")
if err != nil {
return latestFlags{}, err
}
distributionID, err := cmd.Flags().GetString("distribution-id")
if err != nil {
return latestFlags{}, err
}
verbose, err := cmd.Flags().GetBool("verbose")
if err != nil {
return latestFlags{}, err
}
logLevel := zapcore.InfoLevel
if verbose {
logLevel = zapcore.DebugLevel
}
return latestFlags{
ref: ref,
stream: stream,
json: json,
region: region,
bucket: bucket,
distributionID: distributionID,
logLevel: logLevel,
}, nil
}