// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package buildenv contains definitions for the
// environments the Go build system can run in.
package buildenv

import (
	"flag"
	"fmt"
	"strings"
)

const (
	prefix = "https://www.googleapis.com/compute/v1/projects/"
)

// Environment describes the configuration of the infrastructure for a
// coordinator and its buildlet resources running on Google Cloud Platform.
// Staging and Production are the two common build environments.
type Environment struct {
	// The GCP project name that the build infrastructure will be provisioned in.
	// This field may be overridden as necessary without impacting other fields.
	ProjectName string

	// The IsProd flag indicates whether production functionality should be
	// enabled. When true, GCE and Kubernetes builders are enabled and the
	// coordinator serves on 443. Otherwise, GCE and Kubernetes builders are
	// disabled and the coordinator serves on 8119.
	IsProd bool

	// Zone is the GCE zone that the coordinator instance and Kubernetes cluster
	// will run in. This field may be overridden as necessary without impacting
	// other fields.
	Zone string

	// ZonesToClean are the GCE zones that will be periodically cleaned by
	// deleting old VMs. The zero value means that no cleaning will occur.
	// This field is optional.
	ZonesToClean []string

	// StaticIP is the public, static IP address that will be attached to the
	// coordinator instance. The zero value means the address will be looked
	// up by name. This field is optional.
	StaticIP string

	// MachineType is the GCE machine type to use for the coordinator.
	MachineType string

	// KubeMinNodes is the minimum number of nodes in the Kubernetes cluster.
	// The autoscaler will ensure that at least this many nodes is always
	// running despite any scale-down decision.
	KubeMinNodes int64

	// KubeMaxNodes is the maximum number of nodes that the autoscaler can
	// provision in the Kubernetes cluster.
	// If KubeMaxNodes is 0, Kubernetes is not used.
	KubeMaxNodes int64

	// KubeMachineType is the GCE machine type to use for the Kubernetes cluster nodes.
	KubeMachineType string

	// KubeName is the name of the Kubernetes cluster that will be created.
	KubeName string

	// KubePassword is the admin password for the Kubernetes cluster. Its value
	// will be set to a random value at runtime.
	KubePassword string

	// DashURL is the base URL of the build dashboard, ending in a slash.
	DashURL string

	// CoordinatorURL is the location from which the coordinator
	// binary will be downloaded.
	// This is only used by cmd/coordinator/buildongce/create.go when
	// creating the coordinator VM from scratch.
	CoordinatorURL string

	// CoordinatorName is the hostname of the coordinator instance.
	CoordinatorName string

	// BuildletBucket is the GCS bucket that stores buildlet binaries.
	// TODO: rename. this is not just for buildlets; also for bootstrap.
	BuildletBucket string

	// LogBucket is the GCS bucket to which logs are written.
	LogBucket string

	// SnapBucket is the GCS bucket to which snapshots of
	// completed builds (after make.bash, before tests) are
	// written.
	SnapBucket string

	// MaxBuilds is the maximum number of concurrent builds that
	// can run. Zero means unlimit. This is typically only used
	// in a development or staging environment.
	MaxBuilds int
}

// MachineTypeURI returns the URI for the environment's Machine Type.
func (e Environment) MachineTypeURI() string {
	return e.ComputePrefix() + "/zones/" + e.Zone + "/machineTypes/" + e.MachineType
}

// ComputePrefix returns the URI prefix for Compute Engine resources in a project.
func (e Environment) ComputePrefix() string {
	return prefix + e.ProjectName
}

// Region returns the GCE region, derived from its zone.
func (e Environment) Region() string {
	return e.Zone[:strings.LastIndex(e.Zone, "-")]
}

// SnapshotURL returns the absolute URL of the .tar.gz containing a
// built Go tree for the builderType and Go rev (40 character Git
// commit hash). The tarball is suitable for passing to
// (*buildlet.Client).PutTarFromURL.
func (e Environment) SnapshotURL(builderType, rev string) string {
	return fmt.Sprintf("https://storage.googleapis.com/%s/go/%s/%s.tar.gz", e.SnapBucket, builderType, rev)
}

// DashBase returns the base URL of the build dashboard, ending in a slash.
func (e Environment) DashBase() string {
	// TODO(quentin): Should we really default to production? That's what the old code did.
	if e.DashURL != "" {
		return e.DashURL
	}
	return Production.DashURL
}

// ByProjectID returns an Environment for the specified
// project ID. It is currently limited to the symbolic-datum-552
// and go-dashboard-dev projects.
// ByProjectID will panic if the project ID is not known.
func ByProjectID(projectID string) *Environment {
	var envKeys []string

	for k := range possibleEnvs {
		envKeys = append(envKeys, k)
	}

	var env *Environment
	env, ok := possibleEnvs[projectID]
	if !ok {
		panic(fmt.Sprintf("Can't get buildenv for unknown project %q. Possible envs are %s", projectID, envKeys))
	}

	return env
}

// Staging defines the environment that the coordinator and build
// infrastructure is deployed to before it is released to production.
// For local dev, override the project with the program's flag to set
// a custom project.
var Staging = &Environment{
	ProjectName:     "go-dashboard-dev",
	IsProd:          true,
	Zone:            "us-central1-f",
	ZonesToClean:    []string{"us-central1-a", "us-central1-b", "us-central1-f"},
	StaticIP:        "104.154.113.235",
	MachineType:     "n1-standard-1",
	KubeMinNodes:    1,
	KubeMaxNodes:    2,
	KubeName:        "buildlets",
	KubeMachineType: "n1-standard-8",
	DashURL:         "https://go-dashboard-dev.appspot.com/",
	CoordinatorURL:  "https://storage.googleapis.com/dev-go-builder-data/coordinator",
	CoordinatorName: "farmer",
	BuildletBucket:  "dev-go-builder-data",
	LogBucket:       "dev-go-build-log",
	SnapBucket:      "dev-go-build-snap",
}

// Production defines the environment that the coordinator and build
// infrastructure is deployed to for production usage at build.golang.org.
var Production = &Environment{
	ProjectName:     "symbolic-datum-552",
	IsProd:          true,
	Zone:            "us-central1-f",
	ZonesToClean:    []string{"us-central1-f"},
	StaticIP:        "107.178.219.46",
	MachineType:     "n1-standard-4",
	KubeMinNodes:    5,
	KubeMaxNodes:    5, // auto-scaling disabled
	KubeName:        "buildlets",
	KubeMachineType: "n1-standard-32",
	DashURL:         "https://build.golang.org/",
	CoordinatorURL:  "https://storage.googleapis.com/go-builder-data/coordinator",
	CoordinatorName: "farmer",
	BuildletBucket:  "go-builder-data",
	LogBucket:       "go-build-log",
	SnapBucket:      "go-build-snap",
}

var Development = &Environment{
	IsProd:   false,
	StaticIP: "127.0.0.1",
}

// possibleEnvs enumerate the known buildenv.Environment definitions.
var possibleEnvs = map[string]*Environment{
	"dev":                Development,
	"symbolic-datum-552": Production,
	"go-dashboard-dev":   Staging,
}

var (
	registeredFlags bool
	stagingFlag     bool
)

// RegisterFlags registers the "staging" flag. It is required if FromFlags is used.
func RegisterFlags() {
	if !registeredFlags {
		flag.BoolVar(&stagingFlag, "staging", false, "use the staging build coordinator and buildlets")
		registeredFlags = true
	}
}

// FromFlags returns the build environment specified from flags.
// By default it returns the production environment.
func FromFlags() *Environment {
	if !registeredFlags {
		panic("FromFlags called without RegisterFlags")
	}
	if stagingFlag {
		return Staging
	}
	return Production
}
