// goldpushk pushes Gold services to production. See go/goldpushk.
//
// Sample usage:
//
//   Deployment of a specific service:
//     $ goldpushk --service diffserver --instance chrome-gpu
//     $ goldpushk -s diffserver -i chrome-gpu
//
//   Deployment of a specific service across multiple instances:
//     $ goldpushk --service diffserver --instance chrome-gpu,skia
//     $ goldpushk -s diffserver -i chrome-gpu,skia
//
//   Deployment of all instances of a given service across all Gold instances:
//     $ goldpushk --service diffserver --instance all
//     $ goldpushk -s diffserver -i all
//
//   Deployment of all services corresponding to a specific Gold instance:
//     $ goldpushk --service all --instance chrome-gpu
//     $ goldpushk -s all -i chrome-gpu
//
//   Deployment of all instances of a given service, designating one of them as the canary:
//     $ goldpushk --service diffserver --instance all --canary skia:diffserver
//
//   Print out all Gold instances and services goldpushk is able to manage:
//     $ goldpushk --list

package main

import (
	"context"
	"errors"
	"fmt"
	"os"
	"sort"
	"strings"
	"text/tabwriter"

	"github.com/spf13/cobra"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/sklog/glog_and_cloud"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/golden/cmd/goldpushk/goldpushk"
)

const (
	// Wildcard value for command line arguments.
	all = "all"

	// Environment variable with path to buildbot repository checkout directory.
	skiaInfraRootEnvVar = "SKIA_INFRA_ROOT"

	// Git repository with k8s configuration files in YAML format.
	k8sConfigRepoUrl = "https://skia.googlesource.com/k8s-config"
)

var (
	// Required flags.
	flagInstances []string
	flagServices  []string
	flagCanaries  []string

	// Optional flags.
	flagList                       bool
	flagDryRun                     bool
	flagNoCommit                   bool
	flagMinUptimeSeconds           int
	flagUptimePollFrequencySeconds int

	// Flags for debugging.
	flagLogToStdErr bool
	flagVerbose     bool
	flagTesting     bool
)

func main() {
	// Prevent sklog from using glog.
	glog_and_cloud.SetLogger(glog_and_cloud.NewStdErrCloudLogger(glog_and_cloud.SLogNone))

	rootCmd := &cobra.Command{
		Use:  "goldpushk",
		Long: "goldpushk pushes Gold services to production.",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			if flagLogToStdErr {
				glog_and_cloud.SetLogger(glog_and_cloud.NewStdErrCloudLogger(glog_and_cloud.SLogStderr))
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			run(cmd)
		},
	}

	rootCmd.Flags().SortFlags = false
	rootCmd.Flags().BoolVar(&flagList, "list", false, "List known Gold instances and services (tip: try combining this flag with --testing).")
	rootCmd.Flags().StringSliceVarP(&flagInstances, "instances", "i", []string{}, "[REQUIRED] Comma-delimited list of Gold instances to target (e.g. \"skia,flutter\"), or \""+all+"\" to target all instances.")
	rootCmd.Flags().StringSliceVarP(&flagServices, "services", "s", []string{}, "[REQUIRED] Comma-delimited list of services to target (e.g. \"frontend,diffserver\"), or \""+all+"\" to target all services.")
	rootCmd.Flags().StringSliceVarP(&flagCanaries, "canaries", "c", []string{}, "Comma-delimited subset of Gold services to use as canaries, written as instance:service pairs (e.g. \"skia:diffserver,flutter:frontend\")")
	rootCmd.Flags().BoolVar(&flagDryRun, "dryrun", false, "Do everything except applying the new configuration to Kubernetes and committing changes to Git.")
	rootCmd.Flags().BoolVar(&flagNoCommit, "no-commit", false, "Do not commit configuration changes to the k8s-config repository.")
	rootCmd.Flags().IntVar(&flagMinUptimeSeconds, "min-uptime", 30, "Minimum uptime in seconds required for all services before exiting the monitoring step.")
	rootCmd.Flags().IntVar(&flagUptimePollFrequencySeconds, "poll-freq", 3, "How often to poll Kubernetes for service uptimes, in seconds.")
	rootCmd.Flags().BoolVar(&flagLogToStdErr, "logtostderr", false, "Log debug information to stderr. No logs will be produced if this flag is not set.")
	rootCmd.Flags().BoolVar(&flagVerbose, "verbose", false, "Verbose logs. This will log the commands executed and their command-line parameters.")
	rootCmd.Flags().BoolVar(&flagTesting, "testing", false, "Do not deploy any production services; use testing services instead.")

	// Fail with exit code 1 in the presence of invalid flags.
	if _, err := rootCmd.ExecuteC(); err != nil {
		sklog.Errorf("Failed to execute Cobra command: %s", err)
		os.Exit(1)
	}
}

func run(cmd *cobra.Command) {
	// Get set of deployable units. Used as the source of truth across goldpushk.
	var deployableUnitSet goldpushk.DeployableUnitSet
	if flagTesting {
		deployableUnitSet = goldpushk.TestingDeployableUnits()
	} else {
		deployableUnitSet = goldpushk.ProductionDeployableUnits()
	}

	// If --list is passed, print known services and exit. This takes into account flag --testing.
	if flagList {
		if err := listKnownServices(deployableUnitSet); err != nil {
			sklog.Fatalf("Error while printing list of known services: %s", err)
		}
		return
	}

	// If --list was not provided, validate presence of flags --services and --instances.
	if len(flagInstances) == 0 {
		fmt.Println("Error: flag \"instances\" is required.")
		if err := cmd.Usage(); err != nil {
			sklog.Fatalf("Error while printing usage: %s", err)
		}
		os.Exit(1)
	}
	if len(flagServices) == 0 {
		fmt.Println("Error: flag \"services\" is required.")
		if err := cmd.Usage(); err != nil {
			sklog.Fatalf("Error while printing usage: %s", err)
		}
		os.Exit(1)
	}

	// Parse and validate command line flags.
	deployableUnits, canariedDeployableUnits, err := parseAndValidateFlags(deployableUnitSet, flagInstances, flagServices, flagCanaries)
	if err != nil {
		fmt.Printf("Error: %s.\n", err)
		os.Exit(1)
	}

	// Read environment variables.
	skiaInfraRoot, ok := os.LookupEnv(skiaInfraRootEnvVar)
	if !ok {
		fmt.Printf("Error: environment variable %s not set.\n", skiaInfraRootEnvVar)
		os.Exit(1)
	}

	// Build goldpushk instance.
	gpk := goldpushk.New(deployableUnits, canariedDeployableUnits, skiaInfraRoot, flagDryRun, flagNoCommit, flagMinUptimeSeconds, flagUptimePollFrequencySeconds, k8sConfigRepoUrl, flagVerbose)

	// Run goldpushk.
	if err = gpk.Run(context.Background()); err != nil {
		fmt.Printf("Error: %s.\n", err)
		os.Exit(1)
	}
}

// listKnownServices prints out a table of known services.
func listKnownServices(deployableUnitSet goldpushk.DeployableUnitSet) error {
	mode := "production"
	if flagTesting {
		mode = "testing"
	}
	fmt.Printf("Known Gold instances and services (%s):\n", mode)

	// Print out table header.
	w := tabwriter.NewWriter(os.Stdout, 10, 0, 2, ' ', 0)
	if _, err := fmt.Fprintln(w, "\nINSTANCE\tSERVICE\tCANONICAL NAME"); err != nil {
		return skerr.Wrap(err)
	}

	// Print out table body.
	for _, instance := range deployableUnitSet.KnownInstances() {
		for _, service := range deployableUnitSet.KnownServices() {
			unit, ok := deployableUnitSet.Get(goldpushk.DeployableUnitID{Instance: instance, Service: service})
			if ok {
				if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", instance, service, unit.CanonicalName()); err != nil {
					return skerr.Wrap(err)
				}
			}
		}
	}

	// Flush output and return.
	if err := w.Flush(); err != nil {
		return skerr.Wrap(err)
	}
	return nil
}

// containsWildcardValue determines whether or not a flag contains the special
// "all" wildcard value.
func containsWildcardValue(flag []string) bool {
	for _, value := range flag {
		if value == all {
			return true
		}
	}
	return false
}

// parseAndValidateFlags validates the given command line flags, retrieves the
// corresponding DeployableUnits from the given DeployableUnitSet and returns
// them as two separate slices according to whether or not they were marked for
// canarying.
func parseAndValidateFlags(deployableUnitSet goldpushk.DeployableUnitSet, instances, services, canaries []string) (deployableUnits, canariedDeployableUnits []goldpushk.DeployableUnit, err error) {
	// Deduplicate inputs.
	instances = util.SSliceDedup(instances)
	services = util.SSliceDedup(services)
	canaries = util.SSliceDedup(canaries)

	// Determine whether --instances or --services are set to "all".
	allInstances := containsWildcardValue(instances)
	allServices := containsWildcardValue(services)

	// If --instances or --services contain the special "all" value, they should
	// not contain any other values.
	if allInstances && len(instances) != 1 {
		return nil, nil, errors.New("flag --instances should contain either \"all\" or a list of Gold instances, but not both")
	}
	if allServices && len(services) != 1 {
		return nil, nil, errors.New("flag --services should contain either \"all\" or a list of Gold services, but not both")
	}
	if allInstances && allServices {
		return nil, nil, errors.New("cannot set both --instances and --services to \"all\"")
	}

	// Validate instances.
	if !allInstances {
		for _, instanceStr := range instances {
			if !deployableUnitSet.IsKnownInstance(goldpushk.Instance(instanceStr)) {
				return nil, nil, fmt.Errorf("unknown Gold instance: \"%s\"", instanceStr)
			}
		}
	}

	// Validate services.
	if !allServices {
		for _, serviceStr := range services {
			if !deployableUnitSet.IsKnownService(goldpushk.Service(serviceStr)) {
				return nil, nil, fmt.Errorf("unknown Gold service: \"%s\"", serviceStr)
			}
		}
	}

	// This slice will be populated with the subset of the cartesian product of
	// flags --instances and --services that is found in the services map.
	var servicesToDeploy []goldpushk.DeployableUnitID

	// Determines whether or not an instance/service pair should be canaried.
	isMarkedForCanarying := map[goldpushk.DeployableUnitID]bool{}

	// Determine the set of instances over which to iterate to compute the
	// cartesian product of flags --instances and --services.
	var instanceIterationSet []goldpushk.Instance
	if containsWildcardValue(instances) {
		// Handle the "all" value.
		instanceIterationSet = deployableUnitSet.KnownInstances()
	} else {
		for _, instanceStr := range instances {
			instanceIterationSet = append(instanceIterationSet, goldpushk.Instance(instanceStr))
		}
	}

	// Determine the set of services over which to iterate to compute the
	// cartesian product of flags --instances and --services.
	var serviceIterationSet []goldpushk.Service
	if containsWildcardValue(services) {
		// Handle the "all" value.
		serviceIterationSet = deployableUnitSet.KnownServices()
	} else {
		for _, serviceStr := range services {
			serviceIterationSet = append(serviceIterationSet, goldpushk.Service(serviceStr))
		}
	}

	// Iterate over the cartesian product of flags --instances and --services.
	for _, instance := range instanceIterationSet {
		for _, service := range serviceIterationSet {
			id := goldpushk.DeployableUnitID{
				Instance: instance,
				Service:  service,
			}

			// Skip if the current instance/service combination is not found in the services map.
			if _, ok := deployableUnitSet.Get(id); !ok {
				continue
			}

			// Save instance/service pair, which is not marked for canarying by default.
			servicesToDeploy = append(servicesToDeploy, id)
			isMarkedForCanarying[id] = false
		}
	}

	// Fail if --instances and --services didn't match any services in the services map.
	if len(servicesToDeploy) == 0 {
		return nil, nil, errors.New("no known Gold services match the values supplied with --instances and --services")
	}

	// Iterate over the --canaries flag.
	for _, canaryStr := range canaries {
		// Validate format and extract substrings.
		canaryStrSplit := strings.Split(canaryStr, ":")
		if len(canaryStrSplit) != 2 || len(canaryStrSplit[0]) == 0 || len(canaryStrSplit[1]) == 0 {
			return nil, nil, fmt.Errorf("invalid canary format: \"%s\"", canaryStr)
		}

		instance := goldpushk.Instance(canaryStrSplit[0])
		service := goldpushk.Service(canaryStrSplit[1])
		instanceServicePair := goldpushk.DeployableUnitID{
			Instance: instance,
			Service:  service,
		}

		// Validate canary subcomponents.
		if !deployableUnitSet.IsKnownInstance(instance) {
			return nil, nil, fmt.Errorf("invalid canary - unknown Gold instance: \"%s\"", canaryStr)
		}
		if !deployableUnitSet.IsKnownService(service) {
			return nil, nil, fmt.Errorf("invalid canary - unknown Gold service: \"%s\"", canaryStr)
		}

		// Canaries should match the services provided with --instances and --services.
		if _, ok := isMarkedForCanarying[instanceServicePair]; !ok {
			return nil, nil, fmt.Errorf("canary does not match any targeted services: \"%s\"", canaryStr)
		}

		// Mark instance/service pair for canarying.
		isMarkedForCanarying[instanceServicePair] = true
	}

	// Sort services to deploy to generate a deterministic output.
	sort.Slice(servicesToDeploy, func(i, j int) bool {
		a := servicesToDeploy[i]
		b := servicesToDeploy[j]
		return a.Instance < b.Instance || (a.Instance == b.Instance && a.Service < b.Service)
	})

	// Build outputs.
	for _, instanceServicePair := range servicesToDeploy {
		deployment, ok := deployableUnitSet.Get(instanceServicePair)
		if !ok {
			sklog.Fatalf("DeployableUnit \"%s\" not found in deployableUnitSet", deployment.CanonicalName())
		}

		if isMarkedForCanarying[instanceServicePair] {
			canariedDeployableUnits = append(canariedDeployableUnits, deployment)
		} else {
			deployableUnits = append(deployableUnits, deployment)
		}
	}

	// If all services to be deployed are marked for canarying, it probably
	// indicates a user error.
	if len(deployableUnits) == 0 {
		return nil, nil, errors.New("all targeted services are marked for canarying")
	}

	return deployableUnits, canariedDeployableUnits, nil
}
