// Copyright 2019 The Go Cloud Development Kit Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // gocdk-runtimevar demonstrates the use of the Go CDK runtimevar package in a // simple command-line application. package main import ( "context" "flag" "fmt" "log" "os" "time" "github.com/google/subcommands" "gocloud.dev/runtimevar" // Import the runtimevar driver packages we want to be able to open. _ "gocloud.dev/runtimevar/awsparamstore" _ "gocloud.dev/runtimevar/blobvar" _ "gocloud.dev/runtimevar/constantvar" _ "gocloud.dev/runtimevar/filevar" _ "gocloud.dev/runtimevar/gcpruntimeconfig" _ "gocloud.dev/runtimevar/httpvar" ) const helpSuffix = ` See https://gocloud.dev/concepts/urls/ for more background on Go CDK URLs, and sub-packages under gocloud.dev/runtimevar (https://godoc.org/gocloud.dev/runtimevar#pkg-subdirectories) for details on the runtimevar.Variable URL format. ` func main() { os.Exit(run(context.Background())) } func run(ctx context.Context) int { subcommands.Register(subcommands.HelpCommand(), "") subcommands.Register(&catCmd{}, "") subcommands.Register(&watchCmd{}, "") log.SetFlags(0) log.SetPrefix("gocdk-runtimevar: ") flag.Parse() return int(subcommands.Execute(ctx)) } type catCmd struct{} func (*catCmd) Name() string { return "cat" } func (*catCmd) Synopsis() string { return "Print a variable's value to stdout" } func (*catCmd) Usage() string { return `cat Read the current value of the variable from and print it to stdout. Example: gocdk-runtimevar cat "constant://?val=foo&decoder=string"` + helpSuffix } func (*catCmd) SetFlags(_ *flag.FlagSet) {} func (*catCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { if f.NArg() != 1 { f.Usage() return subcommands.ExitUsageError } variableURL := f.Arg(0) // Open a *runtimevar.Variable using the variableURL. variable, err := runtimevar.OpenVariable(ctx, variableURL) if err != nil { log.Printf("Failed to open variable: %v\n", err) return subcommands.ExitFailure } defer variable.Close() snapshot, err := variable.Latest(ctx) if err != nil { log.Printf("Failed to read variable value: %v\n", err) return subcommands.ExitFailure } fmt.Printf("(%T) %v\n", snapshot.Value, snapshot.Value) return subcommands.ExitSuccess } type watchCmd struct{} func (*watchCmd) Name() string { return "watch" } func (*watchCmd) Synopsis() string { return "Watch a variable's value and print changes to stdout" } func (*watchCmd) Usage() string { return `watch Read the value of the variable from and print changes to stdout. Example: gocdk-runtimevar watch "constant://?val=foo&decoder=string"` + helpSuffix } func (*watchCmd) SetFlags(_ *flag.FlagSet) {} func (*watchCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { if f.NArg() != 1 { f.Usage() return subcommands.ExitUsageError } variableURL := f.Arg(0) // Open a *runtimevar.Variable using the variableURL. variable, err := runtimevar.OpenVariable(ctx, variableURL) if err != nil { log.Printf("Failed to open variable: %v\n", err) return subcommands.ExitFailure } defer variable.Close() fmt.Fprintf(os.Stderr, "Watching %s for changes...\n\n", variableURL) time.Sleep(250 * time.Millisecond) // to ensure deterministic combined output for test for { snapshot, err := variable.Watch(ctx) if err != nil { if err == context.Canceled { return subcommands.ExitSuccess } fmt.Printf("(error) %v\n", err) continue } fmt.Printf("(%T) %[1]v\n", snapshot.Value) } return subcommands.ExitSuccess }