blob: 7a07041d875f3ab11ff25747a2959ca8cdc3765d [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The following enables go generate to generate the doc.go file.
//go:generate go run $JIRI_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go . -help
package main
import (
"fmt"
"io/ioutil"
"os/exec"
"strings"
"v.io/v23"
"v.io/v23/context"
"v.io/v23/security"
"v.io/x/lib/cmdline"
"v.io/x/ref/lib/signals"
"v.io/x/ref/lib/v23cmd"
_ "v.io/x/ref/runtime/factories/roaming"
"v.io/x/ref/services/allocator"
"v.io/x/ref/services/cluster"
)
var (
nameFlag string
serverNameFlag string
serverNameRootFlag string
deploymentTemplateFlag string
globalAdminsFlag string
maxInstancesFlag int
maxInstancesPerUserFlag int
diskSizeFlag string
gcloudBinFlag string
kubectlBinFlag string
vkubeBinFlag string
vkubeCfgFlag string
clusterAgentFlag string
blessingSecretFlag string
monitoringKeyFileFlag string
// HTTP flags.
assetsFlag string
httpAddrFlag string
externalURLFlag string
oauthCredsFileFlag string
secureCookiesFlag bool
dashboardGCMMetricFlag string
dashboardGCMProjectFlag string
staticAssetsPrefixFlag string
cmdRoot = &cmdline.Command{
Runner: v23cmd.RunnerFunc(runAllocator),
Name: "allocatord",
Short: "Runs the allocator service",
Long: "Runs the allocator service",
}
)
const (
serverNameFlagName = "server-name"
serverNameRootFlagName = "server-name-root"
oauthCredsFileFlagName = "oauth-client-creds-file"
gcloudFlagName = "gcloud"
kubectlFlagName = "kubectl"
vkubeFlagName = "vkube"
)
func main() {
cmdRoot.Flags.StringVar(&nameFlag, "name", "", "Name to publish for this service.")
cmdRoot.Flags.StringVar(&serverNameFlag, serverNameFlagName, "", "Name of the servers to allocate. This name is part of the published names in the Vanadium namespace and the names of the Deployments in Kubernetes.")
cmdRoot.Flags.StringVar(&serverNameRootFlag, serverNameRootFlagName, "", "Namespace root for allocated servers to use when publishing in the Vanadium namespace. If not set, the namespace root of the allocator server is used.")
cmdRoot.Flags.StringVar(&deploymentTemplateFlag, "deployment-template", "", "The template for the deployment of the servers to allocate.")
cmdRoot.Flags.StringVar(&globalAdminsFlag, "global-admins", "", "A comma-separated list of blessing patterns that have access to all the server instances.")
cmdRoot.Flags.IntVar(&maxInstancesFlag, "max-instances", 10, "The maximum total number of server instances to create.")
cmdRoot.Flags.IntVar(&maxInstancesPerUserFlag, "max-instances-per-user", 1, "The maximum number of server instances to create per user.")
cmdRoot.Flags.StringVar(&diskSizeFlag, "server-disk-size", "50GB", "The size of the persistent disk to allocate with the servers.")
cmdRoot.Flags.StringVar(&gcloudBinFlag, gcloudFlagName, "gcloud", "The gcloud binary to use.")
cmdRoot.Flags.StringVar(&kubectlBinFlag, kubectlFlagName, "kubectl", "The kubectl binary to use.")
cmdRoot.Flags.StringVar(&vkubeBinFlag, vkubeFlagName, "vkube", "The vkube binary to use.")
cmdRoot.Flags.StringVar(&vkubeCfgFlag, "vkube-cfg", "vkube.cfg", "The vkube.cfg to use.")
cmdRoot.Flags.StringVar(&clusterAgentFlag, "cluster-agent", "", "The address of the cluster-agent.")
cmdRoot.Flags.StringVar(&blessingSecretFlag, "blessings-secret-file", "", "If set, this file contains the secret to present to the cluster-agent to get the base blessings for the allocated servers.")
cmdRoot.Flags.StringVar(&assetsFlag, "assets", "", "If set, the directory containing assets (template definitions, css, javascript files etc.) to use in the web interface. If not set, compiled-in assets will be used instead.")
cmdRoot.Flags.StringVar(&httpAddrFlag, "http-addr", "", "Address on which the HTTP server listens on. If empty, no HTTP server is started.")
cmdRoot.Flags.StringVar(&externalURLFlag, "external-url", "", "Public URL for the HTTP server. Must be specified if --http-addr is specified.")
cmdRoot.Flags.StringVar(&monitoringKeyFileFlag, "monitoring-key-file", "", "The path to the service account's JSON credentials file.")
cmdRoot.Flags.StringVar(&oauthCredsFileFlag, oauthCredsFileFlagName, "", "JSON-encoded file containing Google Oauth2 client ID and secret (https://developers.google.com/identity/protocols/OAuth2#basicsteps), as well as the HMAC cookie signing key")
cmdRoot.Flags.BoolVar(&secureCookiesFlag, "secure-cookies", true, "Whether to use only secure cookies. Should be true unless running the server without TLS for testing.")
cmdRoot.Flags.StringVar(&dashboardGCMMetricFlag, "dashboard-gcm-metric", "", "The metric name used to get data from GCM to render dashboard charts.")
cmdRoot.Flags.StringVar(&dashboardGCMProjectFlag, "dashboard-gcm-project", "", "The project name used to get data from GCM to render dashboard charts.")
cmdRoot.Flags.StringVar(&staticAssetsPrefixFlag, "static-assets-prefix", "", "Host serving the web assets.")
cmdline.HideGlobalFlagsExcept()
cmdline.Main(cmdRoot)
}
func checkFlags(ctx *context.T, env *cmdline.Env) error {
if nameRoot(ctx) == "" {
return env.UsageErrorf("--%s not specified, and no default namespace root found", serverNameRootFlagName)
}
for f, b := range map[string]string{gcloudFlagName: gcloudBinFlag, kubectlFlagName: kubectlBinFlag, vkubeFlagName: vkubeBinFlag} {
if _, err := exec.LookPath(b); err != nil {
return env.UsageErrorf("--%s binary %s not found: %v", f, b, err)
}
}
return nil
}
func runAllocator(ctx *context.T, env *cmdline.Env, args []string) error {
if err := checkFlags(ctx, env); err != nil {
return err
}
var (
baseBlessings security.Blessings
baseBlessingNames []string
)
if clusterAgentFlag == "" || blessingSecretFlag == "" {
fmt.Fprintln(env.Stderr, "WARNING: Using self-blessed blessings for allocated servers")
const selfName = "allocator"
var err error
if baseBlessings, err = v23.GetPrincipal(ctx).BlessSelf(selfName); err != nil {
return err
}
baseBlessingNames = []string{selfName}
} else {
secret, err := ioutil.ReadFile(blessingSecretFlag)
if err != nil {
return err
}
baseBlessings, err = cluster.ClusterAgentClient(clusterAgentFlag).SeekBlessings(ctx, strings.TrimSpace(string(secret)))
if err != nil {
return err
}
baseBlessingNames = security.BlessingNames(v23.GetPrincipal(ctx), baseBlessings)
}
ctx, server, err := v23.WithNewServer(
ctx,
nameFlag,
allocator.AllocatorServer(&allocatorImpl{baseBlessings, baseBlessingNames}),
security.AllowEveryone(),
)
if err != nil {
return err
}
ah, err := newAssetsHelper(assetsFlag)
if err != nil {
return err
}
ctx.Infof("Listening on: %v", server.Status().Endpoints)
if httpAddrFlag != "" {
if oauthCredsFileFlag == "" {
return env.UsageErrorf("--%s must be provided", oauthCredsFileFlagName)
}
oauthCreds, err := clientCredsFromFile(oauthCredsFileFlag)
if err != nil {
return err
}
cleanup := startHTTP(ctx, httpArgs{
addr: httpAddrFlag,
externalURL: externalURLFlag,
dashboardGCMMetric: dashboardGCMMetricFlag,
dashboardGCMProject: dashboardGCMProjectFlag,
monitoringKeyFile: monitoringKeyFileFlag,
oauthCreds: oauthCreds,
serverName: serverNameFlag,
secureCookies: secureCookiesFlag,
baseBlessings: baseBlessings,
baseBlessingNames: baseBlessingNames,
staticAssetsPrefix: staticAssetsPrefixFlag,
assets: ah,
})
defer cleanup()
}
<-signals.ShutdownOnSignals(ctx)
return nil
}