github.com/docker/app@v0.9.1-beta3.0.20210611140623-a48f773ab002/internal/commands/validate.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  
     7  	"github.com/docker/app/internal/cliopts"
     8  	"github.com/docker/app/internal/compose"
     9  	"github.com/docker/app/internal/packager"
    10  	"github.com/docker/app/render"
    11  	"github.com/docker/app/types"
    12  	"github.com/docker/cli/cli"
    13  	dockercliopts "github.com/docker/cli/opts"
    14  	"github.com/pkg/errors"
    15  	"github.com/spf13/cobra"
    16  )
    17  
    18  type validateOptions struct {
    19  	cliopts.ParametersOptions
    20  }
    21  
    22  func validateCmd() *cobra.Command {
    23  	var opts validateOptions
    24  	cmd := &cobra.Command{
    25  		Use:         "validate [OPTIONS] APP_DEFINITION",
    26  		Short:       "Check that an App definition (.dockerapp) is syntactically correct",
    27  		Example:     `$ docker app validate myapp.dockerapp --set key=value --parameters-file myparam.yml`,
    28  		Args:        cli.RequiresMaxArgs(1),
    29  		Annotations: map[string]string{"experimentalCLI": "true"},
    30  		RunE: func(cmd *cobra.Command, args []string) error {
    31  			return runValidate(args, opts)
    32  		},
    33  	}
    34  	opts.ParametersOptions.AddFlags(cmd.Flags())
    35  	return cmd
    36  }
    37  
    38  func runValidate(args []string, opts validateOptions) error {
    39  	app, err := packager.Extract(firstOrEmpty(args),
    40  		types.WithParametersFiles(opts.ParametersFiles...),
    41  	)
    42  	if err != nil {
    43  		return err
    44  	}
    45  	defer app.Cleanup()
    46  	argParameters := dockercliopts.ConvertKVStringsToMap(opts.Overrides)
    47  	_, err = render.Render(app, argParameters, nil)
    48  	if err != nil {
    49  		return err
    50  	}
    51  
    52  	vars, err := compose.ExtractVariables(app.Composes()[0], compose.ExtrapolationPattern)
    53  	if err != nil {
    54  		return errors.Wrap(err, "failed to parse compose file")
    55  	}
    56  	for k := range app.Parameters().Flatten() {
    57  		if _, ok := vars[k]; !ok {
    58  			return fmt.Errorf("%s is declared as parameter but not used by the compose file", k)
    59  		}
    60  	}
    61  
    62  	fmt.Fprintf(os.Stdout, "Validated %q\n", app.Path)
    63  	return nil
    64  }
    65  
    66  func firstOrEmpty(list []string) string {
    67  	if len(list) != 0 {
    68  		return list[0]
    69  	}
    70  	return ""
    71  }