<commit_before>package main

import (
	"flag"
	"os"
	"os/signal"
	"syscall"

	"github.com/golang/glog"
	"github.com/libopenstorage/stork/drivers/volume"
	_ "github.com/libopenstorage/stork/drivers/volume/portworx"
	"github.com/libopenstorage/stork/pkg/extender"
	"github.com/libopenstorage/stork/pkg/monitor"
	"github.com/libopenstorage/stork/pkg/snapshot"
	log "github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	api_v1 "k8s.io/api/core/v1"
	clientset "k8s.io/client-go/kubernetes"
	core_v1 "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/leaderelection"
	"k8s.io/client-go/tools/leaderelection/resourcelock"
	"k8s.io/client-go/tools/record"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/leaderelectionconfig"
)

var ext *extender.Extender

func main() {
	// Parse empty flags to suppress warnings from the snapshotter which uses
	// glog
	err := flag.CommandLine.Parse([]string{})
	if err != nil {
		log.Warnf("Error parsing flag: %v", err)
	}
	err = flag.Set("logtostderr", "true")
	if err != nil {
		log.Fatalf("Error setting glog flag: %v", err)
	}

	app := cli.NewApp()
	app.Name = "stork"
	app.Usage = "STorage Orchestartor Runtime for Kubernetes (STORK)"
	app.Version = "0.3"
	app.Action = run

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "Enable verbose logging",
		},
		cli.StringFlag{
			Name:  "driver,d",
			Usage: "Storage driver name",
		},
		cli.BoolTFlag{
			Name:  "leader-elect",
			Usage: "Enable leader election",
		},
		cli.StringFlag{
			Name:  "lock-object-name",
			Usage: "Name for the lock object (default: stork)",
			Value: "stork",
		},
		cli.StringFlag{
			Name:  "lock-object-namespace",
			Usage: "Namespace for the lock object (default: kube-system)",
			Value: "kube-system",
		},
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatalf("Error starting stork: %v", err)
	}
}
func run(c *cli.Context) {

	driverName := c.String("driver")
	if len(driverName) == 0 {
		log.Fatalf("driver option is required")
		os.Exit(-1)
	}

	verbose := c.Bool("verbose")
	if verbose {
		log.SetLevel(log.DebugLevel)
	}

	d, err := volume.Get(driverName)
	if err != nil {
		log.Fatalf("Error getting Stork Driver %v: %v", driverName, err)
		os.Exit(-1)
	}

	if err = d.Init(nil); err != nil {
		log.Fatalf("Error initializing Stork Driver %v: %v", driverName, err)
		os.Exit(-1)
	}

	ext = &extender.Extender{
		Driver: d,
	}

	if err = ext.Start(); err != nil {
		log.Fatalf("Error starting scheduler extender: %v", err)
		os.Exit(-1)
	}

	runFunc := func(_ <-chan struct{}) {
		runStork(d)
	}

	leaderConfig := leaderelectionconfig.DefaultLeaderElectionConfiguration()
	leaderConfig.LeaderElect = c.BoolT("leader-elect")

	if leaderConfig.LeaderElect {
		config, err := rest.InClusterConfig()
		if err != nil {
			log.Fatalf("Error getting cluster config: %v", err)
			os.Exit(-1)
		}

		k8sClient, err := clientset.NewForConfig(config)
		if err != nil {
			log.Fatalf("Error getting client, %v", err)
			os.Exit(-1)
		}

		leaderConfig.ResourceLock = resourcelock.ConfigMapsResourceLock
		lockObjectName := c.String("lock-object-name")
		lockObjectNamespace := c.String("lock-object-namespace")

		eventBroadcaster := record.NewBroadcaster()
		eventBroadcaster.StartLogging(glog.Infof)
		eventBroadcaster.StartRecordingToSink(&core_v1.EventSinkImpl{Interface: core_v1.New(k8sClient.Core().RESTClient()).Events("")})
		recorder := eventBroadcaster.NewRecorder(api.Scheme, api_v1.EventSource{Component: "stork"})

		id, err := os.Hostname()
		if err != nil {
			log.Fatalf("Error getting hostname: %v", err)
			os.Exit(-1)
		}

		lockConfig := resourcelock.ResourceLockConfig{
			Identity:      id,
			EventRecorder: recorder,
		}

		resourceLock, err := resourcelock.New(
			leaderConfig.ResourceLock,
			lockObjectNamespace,
			lockObjectName,
			k8sClient.CoreV1(),
			lockConfig)
		if err != nil {
			log.Fatalf("Error creating resource lock: %v", err)
			os.Exit(-1)
		}

		leaderElector, err := leaderelection.NewLeaderElector(
			leaderelection.LeaderElectionConfig{
				Lock:          resourceLock,
				LeaseDuration: leaderConfig.LeaseDuration.Duration,
				RenewDeadline: leaderConfig.RenewDeadline.Duration,
				RetryPeriod:   leaderConfig.RetryPeriod.Duration,

				Callbacks: leaderelection.LeaderCallbacks{
					OnStartedLeading: runFunc,
					OnStoppedLeading: func() {
						log.Fatalf("Stork lost master")
					},
				},
			})
		if err != nil {
			log.Fatalf("Error creating leader elector: %v", err)
			os.Exit(-1)
		}

		leaderElector.Run()
	} else {
		runFunc(nil)
	}
}

func runStork(d volume.Driver) {
	monitor := &monitor.Monitor{
		Driver: d,
	}

	if err := monitor.Start(); err != nil {
		log.Fatalf("Error starting storage monitor: %v", err)
		os.Exit(-1)
	}

	snapshotController := &snapshotcontroller.SnapshotController{
		Driver: d,
	}

	if err := snapshotController.Start(); err != nil {
		log.Fatalf("Error starting snapshot controller: %v", err)
		os.Exit(-1)
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
	for {
		select {
		case <-signalChan:
			log.Printf("Shutdown signal received, exiting...")
			if err := ext.Stop(); err != nil {
				log.Warnf("Error stopping extender: %v", err)
			}
			if err := monitor.Stop(); err != nil {
				log.Warnf("Error stopping monitor: %v", err)
			}
			if err := snapshotController.Stop(); err != nil {
				log.Warnf("Error stopping snapshot controller: %v", err)
			}
			os.Exit(0)
		}
	}
}
<commit_msg>Update version to 0.3.1<commit_after>package main

import (
	"flag"
	"os"
	"os/signal"
	"syscall"

	"github.com/golang/glog"
	"github.com/libopenstorage/stork/drivers/volume"
	_ "github.com/libopenstorage/stork/drivers/volume/portworx"
	"github.com/libopenstorage/stork/pkg/extender"
	"github.com/libopenstorage/stork/pkg/monitor"
	"github.com/libopenstorage/stork/pkg/snapshot"
	log "github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	api_v1 "k8s.io/api/core/v1"
	clientset "k8s.io/client-go/kubernetes"
	core_v1 "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/leaderelection"
	"k8s.io/client-go/tools/leaderelection/resourcelock"
	"k8s.io/client-go/tools/record"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/leaderelectionconfig"
)

var ext *extender.Extender

func main() {
	// Parse empty flags to suppress warnings from the snapshotter which uses
	// glog
	err := flag.CommandLine.Parse([]string{})
	if err != nil {
		log.Warnf("Error parsing flag: %v", err)
	}
	err = flag.Set("logtostderr", "true")
	if err != nil {
		log.Fatalf("Error setting glog flag: %v", err)
	}

	app := cli.NewApp()
	app.Name = "stork"
	app.Usage = "STorage Orchestartor Runtime for Kubernetes (STORK)"
	app.Version = "0.3.1"
	app.Action = run

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "Enable verbose logging",
		},
		cli.StringFlag{
			Name:  "driver,d",
			Usage: "Storage driver name",
		},
		cli.BoolTFlag{
			Name:  "leader-elect",
			Usage: "Enable leader election",
		},
		cli.StringFlag{
			Name:  "lock-object-name",
			Usage: "Name for the lock object (default: stork)",
			Value: "stork",
		},
		cli.StringFlag{
			Name:  "lock-object-namespace",
			Usage: "Namespace for the lock object (default: kube-system)",
			Value: "kube-system",
		},
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatalf("Error starting stork: %v", err)
	}
}
func run(c *cli.Context) {

	driverName := c.String("driver")
	if len(driverName) == 0 {
		log.Fatalf("driver option is required")
		os.Exit(-1)
	}

	verbose := c.Bool("verbose")
	if verbose {
		log.SetLevel(log.DebugLevel)
	}

	d, err := volume.Get(driverName)
	if err != nil {
		log.Fatalf("Error getting Stork Driver %v: %v", driverName, err)
		os.Exit(-1)
	}

	if err = d.Init(nil); err != nil {
		log.Fatalf("Error initializing Stork Driver %v: %v", driverName, err)
		os.Exit(-1)
	}

	ext = &extender.Extender{
		Driver: d,
	}

	if err = ext.Start(); err != nil {
		log.Fatalf("Error starting scheduler extender: %v", err)
		os.Exit(-1)
	}

	runFunc := func(_ <-chan struct{}) {
		runStork(d)
	}

	leaderConfig := leaderelectionconfig.DefaultLeaderElectionConfiguration()
	leaderConfig.LeaderElect = c.BoolT("leader-elect")

	if leaderConfig.LeaderElect {
		config, err := rest.InClusterConfig()
		if err != nil {
			log.Fatalf("Error getting cluster config: %v", err)
			os.Exit(-1)
		}

		k8sClient, err := clientset.NewForConfig(config)
		if err != nil {
			log.Fatalf("Error getting client, %v", err)
			os.Exit(-1)
		}

		leaderConfig.ResourceLock = resourcelock.ConfigMapsResourceLock
		lockObjectName := c.String("lock-object-name")
		lockObjectNamespace := c.String("lock-object-namespace")

		eventBroadcaster := record.NewBroadcaster()
		eventBroadcaster.StartLogging(glog.Infof)
		eventBroadcaster.StartRecordingToSink(&core_v1.EventSinkImpl{Interface: core_v1.New(k8sClient.Core().RESTClient()).Events("")})
		recorder := eventBroadcaster.NewRecorder(api.Scheme, api_v1.EventSource{Component: "stork"})

		id, err := os.Hostname()
		if err != nil {
			log.Fatalf("Error getting hostname: %v", err)
			os.Exit(-1)
		}

		lockConfig := resourcelock.ResourceLockConfig{
			Identity:      id,
			EventRecorder: recorder,
		}

		resourceLock, err := resourcelock.New(
			leaderConfig.ResourceLock,
			lockObjectNamespace,
			lockObjectName,
			k8sClient.CoreV1(),
			lockConfig)
		if err != nil {
			log.Fatalf("Error creating resource lock: %v", err)
			os.Exit(-1)
		}

		leaderElector, err := leaderelection.NewLeaderElector(
			leaderelection.LeaderElectionConfig{
				Lock:          resourceLock,
				LeaseDuration: leaderConfig.LeaseDuration.Duration,
				RenewDeadline: leaderConfig.RenewDeadline.Duration,
				RetryPeriod:   leaderConfig.RetryPeriod.Duration,

				Callbacks: leaderelection.LeaderCallbacks{
					OnStartedLeading: runFunc,
					OnStoppedLeading: func() {
						log.Fatalf("Stork lost master")
					},
				},
			})
		if err != nil {
			log.Fatalf("Error creating leader elector: %v", err)
			os.Exit(-1)
		}

		leaderElector.Run()
	} else {
		runFunc(nil)
	}
}

func runStork(d volume.Driver) {
	monitor := &monitor.Monitor{
		Driver: d,
	}

	if err := monitor.Start(); err != nil {
		log.Fatalf("Error starting storage monitor: %v", err)
		os.Exit(-1)
	}

	snapshotController := &snapshotcontroller.SnapshotController{
		Driver: d,
	}

	if err := snapshotController.Start(); err != nil {
		log.Fatalf("Error starting snapshot controller: %v", err)
		os.Exit(-1)
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
	for {
		select {
		case <-signalChan:
			log.Printf("Shutdown signal received, exiting...")
			if err := ext.Stop(); err != nil {
				log.Warnf("Error stopping extender: %v", err)
			}
			if err := monitor.Stop(); err != nil {
				log.Warnf("Error stopping monitor: %v", err)
			}
			if err := snapshotController.Stop(); err != nil {
				log.Warnf("Error stopping snapshot controller: %v", err)
			}
			os.Exit(0)
		}
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/exercism/cli/config"
	"github.com/exercism/cli/workspace"
	"github.com/stretchr/testify/assert"
)

func TestSubmit(t *testing.T) {
	oldOut := Out
	oldErr := Err
	oldIn := In
	Out = ioutil.Discard
	Err = ioutil.Discard
	defer func() {
		Out = oldOut
		Err = oldErr
		In = oldIn
	}()

	type file struct {
		relativePath string
		contents     string
	}

	file1 := file{
		relativePath: "file-1.txt",
		contents:     "This is file 1.",
	}
	file2 := file{
		relativePath: filepath.Join("subdir", "file-2.txt"),
		contents:     "This is file 2.",
	}
	file3 := file{
		relativePath: "README.md",
		contents:     "The readme.",
	}

	cmdTest := &CommandTest{
		Cmd:                     submitCmd,
		InitFn:                  initSubmitCmd,
		MockInteractiveResponse: "\n",
		Args: []string{"fakeapp", "submit", "-e", "bogus-exercise", "-t", "bogus-track"},
	}
	cmdTest.Setup(t)
	defer cmdTest.Teardown(t)

	// Create a temp dir for the config and the exercise files.
	dir := filepath.Join(cmdTest.TmpDir, "bogus-track", "bogus-exercise")
	os.MkdirAll(filepath.Join(dir, "subdir"), os.FileMode(0755))

	solution := &workspace.Solution{
		ID:          "bogus-solution-uuid",
		Track:       "bogus-track",
		Exercise:    "bogus-exercise",
		IsRequester: true,
	}
	err := solution.Write(dir)
	assert.NoError(t, err)

	for _, file := range []file{file1, file2, file3} {
		err := ioutil.WriteFile(filepath.Join(dir, file.relativePath), []byte(file.contents), os.FileMode(0755))
		assert.NoError(t, err)
	}

	// The fake endpoint will populate this when it receives the call from the command.
	submittedFiles := map[string]string{}

	// Set up the test server.
	fakeEndpoint := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		err := r.ParseMultipartForm(2 << 10)
		if err != nil {
			t.Fatal(err)
		}
		mf := r.MultipartForm

		files := mf.File["files[]"]
		for _, fileHeader := range files {
			file, err := fileHeader.Open()
			if err != nil {
				t.Fatal(err)
			}
			defer file.Close()
			body, err := ioutil.ReadAll(file)
			if err != nil {
				t.Fatal(err)
			}
			submittedFiles[fileHeader.Filename] = string(body)
		}
	})
	ts := httptest.NewServer(fakeEndpoint)
	defer ts.Close()

	// Create a fake user config.
	usrCfg := config.NewEmptyUserConfig()
	usrCfg.Workspace = cmdTest.TmpDir
	usrCfg.APIBaseURL = ts.URL
	err = usrCfg.Write()
	assert.NoError(t, err)

	// Create a fake CLI config.
	cliCfg, err := config.NewCLIConfig()
	assert.NoError(t, err)
	cliCfg.Tracks["bogus-track"] = config.NewTrack("bogus-track")
	err = cliCfg.Write()
	assert.NoError(t, err)

	// Write mock interactive input to In for the CLI command.
	In = strings.NewReader(cmdTest.MockInteractiveResponse)

	// Execute the command!
	cmdTest.App.Execute()

	// We got only the file we expected.
	assert.Equal(t, 2, len(submittedFiles))
	for _, file := range []file{file1, file2} {
		path := string(os.PathSeparator) + file.relativePath
		assert.Equal(t, file.contents, submittedFiles[path])
	}
}
<commit_msg>Refactor submit command tests to use table tests<commit_after>package cmd

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/exercism/cli/config"
	"github.com/exercism/cli/workspace"
	"github.com/stretchr/testify/assert"
)

func TestSubmit(t *testing.T) {
	oldOut := Out
	oldErr := Err
	oldIn := In
	Out = ioutil.Discard
	Err = ioutil.Discard
	defer func() {
		Out = oldOut
		Err = oldErr
		In = oldIn
	}()

	type file struct {
		relativePath string
		contents     string
	}

	file1 := file{
		relativePath: "file-1.txt",
		contents:     "This is file 1.",
	}
	file2 := file{
		relativePath: filepath.Join("subdir", "file-2.txt"),
		contents:     "This is file 2.",
	}
	file3 := file{
		relativePath: "README.md",
		contents:     "The readme.",
	}
	// make a list of tests
	cmdTestFlags := &CommandTest{
		Cmd:                     submitCmd,
		InitFn:                  initSubmitCmd,
		MockInteractiveResponse: "\n",
		Args: []string{"fakeapp", "submit", "-e", "bogus-exercise", "-t", "bogus-track"},
	}
	cmdTestRelativeDir := &CommandTest{
		Cmd:                     submitCmd,
		InitFn:                  initSubmitCmd,
		MockInteractiveResponse: "\n",
		Args: []string{"fakeapp", "submit", filepath.Join("bogus-track", "bogus-exercise")},
	}
	tests := []*CommandTest{
		cmdTestFlags,
		cmdTestRelativeDir,
	}
	for _, cmdTest := range tests {
		cmdTest.Setup(t)
		defer cmdTest.Teardown(t)

		// handle case when directory to submit needs the tmp dir prefix
		if len(cmdTest.Args) == 3 {
			cmdTest.Args[2] = filepath.Join(cmdTest.TmpDir, cmdTest.Args[2])
		}

		// Create a temp dir for the config and the exercise files.
		dir := filepath.Join(cmdTest.TmpDir, "bogus-track", "bogus-exercise")
		os.MkdirAll(filepath.Join(dir, "subdir"), os.FileMode(0755))

		solution := &workspace.Solution{
			ID:          "bogus-solution-uuid",
			Track:       "bogus-track",
			Exercise:    "bogus-exercise",
			IsRequester: true,
		}
		err := solution.Write(dir)
		assert.NoError(t, err)

		for _, file := range []file{file1, file2, file3} {
			err := ioutil.WriteFile(filepath.Join(dir, file.relativePath), []byte(file.contents), os.FileMode(0755))
			assert.NoError(t, err)
		}

		// The fake endpoint will populate this when it receives the call from the command.
		submittedFiles := map[string]string{}

		// Set up the test server.
		fakeEndpoint := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			err := r.ParseMultipartForm(2 << 10)
			if err != nil {
				t.Fatal(err)
			}
			mf := r.MultipartForm

			files := mf.File["files[]"]
			for _, fileHeader := range files {
				file, err := fileHeader.Open()
				if err != nil {
					t.Fatal(err)
				}
				defer file.Close()
				body, err := ioutil.ReadAll(file)
				if err != nil {
					t.Fatal(err)
				}
				submittedFiles[fileHeader.Filename] = string(body)
			}
		})
		ts := httptest.NewServer(fakeEndpoint)
		defer ts.Close()

		// Create a fake user config.
		usrCfg := config.NewEmptyUserConfig()
		usrCfg.Workspace = cmdTest.TmpDir
		usrCfg.APIBaseURL = ts.URL
		err = usrCfg.Write()
		assert.NoError(t, err)

		// Create a fake CLI config.
		cliCfg, err := config.NewCLIConfig()
		assert.NoError(t, err)
		cliCfg.Tracks["bogus-track"] = config.NewTrack("bogus-track")
		err = cliCfg.Write()
		assert.NoError(t, err)

		// Write mock interactive input to In for the CLI command.
		In = strings.NewReader(cmdTest.MockInteractiveResponse)

		// Execute the command!
		cmdTest.App.Execute()

		// We got only the file we expected.
		assert.Equal(t, 2, len(submittedFiles))
		for _, file := range []file{file1, file2} {
			path := string(os.PathSeparator) + file.relativePath
			assert.Equal(t, file.contents, submittedFiles[path])
		}
	}
}
<|endoftext|>


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

//go:generate ./mkdoc.sh

package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"sort"
	"strings"

	// We deliberately use native Go logs for this command-line tool
	// as there is no need to report errors to GCP.
	// Our dependencies will still use the Upspin logs
	"log"

	"upspin.io/cmd/cacheserver/cacheutil"
	"upspin.io/config"
	"upspin.io/flags"
	"upspin.io/metric"
	"upspin.io/subcmd"

	// Load useful packers
	_ "upspin.io/pack/ee"
	_ "upspin.io/pack/eeintegrity"
	_ "upspin.io/pack/plain"

	// Load required transports
	"upspin.io/transports"
)

const intro = `
The upspin command provides utilities for creating and administering
Upspin files, users, and servers. Although Upspin data is often
accessed through the host file system using upspinfs, the upspin
command is necessary for other tasks, such as: changing a user's
keys (upspin user); updating the wrapped keys after access permissions
are changed (upspin share); or seeing all the information about an
Upspin file beyond what is visible through the host file system
(upspin info). It can also be used separately from upspinfs to
create, read, and update files.

Each subcommand has a -help flag that explains it in more detail.
For instance

	upspin user -help

explains the purpose and usage of the user subcommand.

There is a set of global flags such as -config to identify the
configuration file to use (default $HOME/upspin/config) and -log
to set the logging level for debugging. These flags apply across
the subcommands.

Each subcommand has its own set of flags, which if used must appear
after the subcommand name. For example, to run the ls command with
its -l flag and debugging enabled, run

	upspin -log debug ls -l

For a list of available subcommands and global flags, run

	upspin -help
`

var commands = map[string]func(*State, ...string){
	"countersign":   (*State).countersign,
	"cp":            (*State).cp,
	"deletestorage": (*State).deletestorage,
	"get":           (*State).get,
	"getref":        (*State).getref,
	"info":          (*State).info,
	"keygen":        (*State).keygen,
	"link":          (*State).link,
	"ls":            (*State).ls,
	"mkdir":         (*State).mkdir,
	"put":           (*State).put,
	"repack":        (*State).repack,
	"rotate":        (*State).rotate,
	"rm":            (*State).rm,
	"setupdomain":   (*State).setupdomain,
	"setupserver":   (*State).setupserver,
	"setupwriters":  (*State).setupwriters,
	"share":         (*State).share,
	"signup":        (*State).signup,
	"snapshot":      (*State).snapshot,
	"tar":           (*State).tar,
	"user":          (*State).user,
	"whichaccess":   (*State).whichAccess,
}

type State struct {
	*subcmd.State
	sharer       *Sharer
	metricsSaver metric.Saver
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("upspin: ")
	flag.Usage = usage
	flags.Parse() // enable all flags

	if len(flag.Args()) < 1 {
		fmt.Fprintln(os.Stderr, intro)
		os.Exit(2)
	}

	op := strings.ToLower(flag.Arg(0))
	state := newState(op)
	args := flag.Args()[1:]

	// Start the cache if needed.
	cacheutil.Start(state.Config)

	// Shell cannot be in commands because of the initialization loop,
	// and anyway we should avoid recursion in the interpreter.
	if state.Name == "shell" {
		state.shell(args...)
		return
	}
	state.getCommand(state.Name)(state, args...)
	state.Cleanup()
	os.Exit(state.ExitCode)
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage of upspin:\n")
	fmt.Fprintf(os.Stderr, "\tupspin [globalflags] <command> [flags] <path>\n")
	printCommands()
	fmt.Fprintf(os.Stderr, "Global flags:\n")
	flag.PrintDefaults()
	os.Exit(2)
}

// printCommands shows the available commands, including those installed
// as separate binaries called "upspin-foo".
func printCommands() {
	fmt.Fprintf(os.Stderr, "Upspin commands:\n")
	var cmdStrs []string
	for cmd := range commands {
		if cmd == "gendoc" {
			continue // never show this in usage
		}
		cmdStrs = append(cmdStrs, cmd)
	}
	// Now find all the binaries in the $PATH.
	cmdStrs = append(cmdStrs, findUpspinBinaries()...)
	sort.Strings(cmdStrs)
	fmt.Fprintf(os.Stderr, "\tshell (Interactive mode)\n")
	// There may be dups; filter them.
	prev := ""
	for _, cmd := range cmdStrs {
		if cmd == prev {
			continue
		}
		prev = cmd
		fmt.Fprintf(os.Stderr, "\t%s\n", cmd)
	}
}

// getCommand looks up the command named by op.
// If it's in the commands tables, we're done.
// If not, it looks for a binary with the equivalent name
// (upspin foo is implemented by upspin-foo).
// If the command still can't be found, it exits after listing the
// commands that do exist.
func (s *State) getCommand(op string) func(*State, ...string) {
	fn := commands[op]
	if fn != nil {
		return fn
	}
	path, err := exec.LookPath("upspin-" + op)
	if err == nil {
		return func(s *State, args ...string) {
			s.runCommand(path, append(flags.Args(), args...)...)
		}
	}
	fmt.Fprintf(os.Stderr, "upspin: no such command %q\n", op)
	printCommands()
	os.Exit(2)
	return nil
}

func (s *State) runCommand(path string, args ...string) {
	cmd := exec.Command(path, args...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		s.Exit(err)
	}
}

func newState(name string) *State {
	s := &State{
		State: subcmd.NewState(name),
	}
	if name == "signup" || name == "keygen" {
		// signup is special since there is no user yet.
		// keygen simply does not require a config or anything else.
		return s
	}
	cfg, err := config.FromFile(flags.Config)
	if err != nil && err != config.ErrNoFactotum {
		s.Exit(err)
	}
	transports.Init(cfg)
	s.State.Init(cfg)
	s.sharer = newSharer(s)
	s.enableMetrics()
	return s
}
<commit_msg>cmd/upspin: look up command name before setting config<commit_after>// Copyright 2016 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:generate ./mkdoc.sh

package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"sort"
	"strings"

	// We deliberately use native Go logs for this command-line tool
	// as there is no need to report errors to GCP.
	// Our dependencies will still use the Upspin logs
	"log"

	"upspin.io/cmd/cacheserver/cacheutil"
	"upspin.io/config"
	"upspin.io/flags"
	"upspin.io/metric"
	"upspin.io/subcmd"

	// Load useful packers
	_ "upspin.io/pack/ee"
	_ "upspin.io/pack/eeintegrity"
	_ "upspin.io/pack/plain"

	// Load required transports
	"upspin.io/transports"
)

const intro = `
The upspin command provides utilities for creating and administering
Upspin files, users, and servers. Although Upspin data is often
accessed through the host file system using upspinfs, the upspin
command is necessary for other tasks, such as: changing a user's
keys (upspin user); updating the wrapped keys after access permissions
are changed (upspin share); or seeing all the information about an
Upspin file beyond what is visible through the host file system
(upspin info). It can also be used separately from upspinfs to
create, read, and update files.

Each subcommand has a -help flag that explains it in more detail.
For instance

	upspin user -help

explains the purpose and usage of the user subcommand.

There is a set of global flags such as -config to identify the
configuration file to use (default $HOME/upspin/config) and -log
to set the logging level for debugging. These flags apply across
the subcommands.

Each subcommand has its own set of flags, which if used must appear
after the subcommand name. For example, to run the ls command with
its -l flag and debugging enabled, run

	upspin -log debug ls -l

For a list of available subcommands and global flags, run

	upspin -help
`

var commands = map[string]func(*State, ...string){
	"countersign":   (*State).countersign,
	"cp":            (*State).cp,
	"deletestorage": (*State).deletestorage,
	"get":           (*State).get,
	"getref":        (*State).getref,
	"info":          (*State).info,
	"keygen":        (*State).keygen,
	"link":          (*State).link,
	"ls":            (*State).ls,
	"mkdir":         (*State).mkdir,
	"put":           (*State).put,
	"repack":        (*State).repack,
	"rotate":        (*State).rotate,
	"rm":            (*State).rm,
	"setupdomain":   (*State).setupdomain,
	"setupserver":   (*State).setupserver,
	"setupwriters":  (*State).setupwriters,
	"share":         (*State).share,
	"signup":        (*State).signup,
	"snapshot":      (*State).snapshot,
	"tar":           (*State).tar,
	"user":          (*State).user,
	"whichaccess":   (*State).whichAccess,
}

type State struct {
	*subcmd.State
	sharer       *Sharer
	metricsSaver metric.Saver
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("upspin: ")
	flag.Usage = usage
	flags.Parse() // enable all flags

	if len(flag.Args()) < 1 {
		fmt.Fprintln(os.Stderr, intro)
		os.Exit(2)
	}

	op := strings.ToLower(flag.Arg(0))
	state := newState(op)
	args := flag.Args()[1:]

	// Shell cannot be in commands because of the initialization loop,
	// and anyway we should avoid recursion in the interpreter.
	if state.Name == "shell" {
		// Start the cache if needed.
		state.init()
		cacheutil.Start(state.Config)
		state.shell(args...)
		return
	}
	cmd := state.getCommand(state.Name)
	state.init()
	cmd(state, args...)
	state.Cleanup()
	os.Exit(state.ExitCode)
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage of upspin:\n")
	fmt.Fprintf(os.Stderr, "\tupspin [globalflags] <command> [flags] <path>\n")
	printCommands()
	fmt.Fprintf(os.Stderr, "Global flags:\n")
	flag.PrintDefaults()
	os.Exit(2)
}

// printCommands shows the available commands, including those installed
// as separate binaries called "upspin-foo".
func printCommands() {
	fmt.Fprintf(os.Stderr, "Upspin commands:\n")
	var cmdStrs []string
	for cmd := range commands {
		if cmd == "gendoc" {
			continue // never show this in usage
		}
		cmdStrs = append(cmdStrs, cmd)
	}
	// Now find all the binaries in the $PATH.
	cmdStrs = append(cmdStrs, findUpspinBinaries()...)
	sort.Strings(cmdStrs)
	fmt.Fprintf(os.Stderr, "\tshell (Interactive mode)\n")
	// There may be dups; filter them.
	prev := ""
	for _, cmd := range cmdStrs {
		if cmd == prev {
			continue
		}
		prev = cmd
		fmt.Fprintf(os.Stderr, "\t%s\n", cmd)
	}
}

// getCommand looks up the command named by op.
// If it's in the commands tables, we're done.
// If not, it looks for a binary with the equivalent name
// (upspin foo is implemented by upspin-foo).
// If the command still can't be found, it exits after listing the
// commands that do exist.
func (s *State) getCommand(op string) func(*State, ...string) {
	fn := commands[op]
	if fn != nil {
		return fn
	}
	path, err := exec.LookPath("upspin-" + op)
	if err == nil {
		return func(s *State, args ...string) {
			s.runCommand(path, append(flags.Args(), args...)...)
		}
	}
	fmt.Fprintf(os.Stderr, "upspin: no such command %q\n", op)
	printCommands()
	os.Exit(2)
	return nil
}

func (s *State) runCommand(path string, args ...string) {
	cmd := exec.Command(path, args...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		s.Exit(err)
	}
}

// newState returns a State with enough initialized to run exit, etc.
// It does not contain a Config.
func newState(name string) *State {
	s := &State{
		State: subcmd.NewState(name),
	}
	return s
}

// init initializes the State with what is required to run the subcommand,
// usually including setting up a Config.
func (s *State) init() {
	// signup is special since there is no user yet.
	// keygen simply does not require a config or anything else.
	if s.Name != "signup" && s.Name != "keygen" {
		cfg, err := config.FromFile(flags.Config)
		if err != nil && err != config.ErrNoFactotum {
			s.Exit(err)
		}
		transports.Init(cfg)
		s.State.Init(cfg)
		s.sharer = newSharer(s)
	}
	s.enableMetrics()
	return
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"hash/fnv"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	statsd "github.com/DataDog/datadog-go/statsd"
	log "github.com/Sirupsen/logrus"
)

var (
	configFile = flag.String("f", "", "The config file to read for settings.")
)

func main() {

	flag.Parse()

	if configFile == nil || *configFile == "" {
		log.Fatal("You must specify a config file")
	}

	config, err := ReadConfig(*configFile)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Error reading config file")
	}

	// Parse the command-line flags.
	flag.Parse()

	if config.Debug {
		log.SetLevel(log.DebugLevel)
		log.WithFields(log.Fields{
			"config": config,
		}).Debug("Starting with config")
	}

	stats, err := statsd.New(config.StatsAddr)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Error creating statsd logging")
	}
	stats.Namespace = "veneur."

	// Start the dispatcher.
	log.WithFields(log.Fields{
		"number": config.NumWorkers,
	}).Info("Starting workers")
	workers := make([]*Worker, config.NumWorkers)
	for i := 0; i < config.NumWorkers; i++ {
		worker := NewWorker(i+1, config)
		worker.Start()
		workers[i] = worker
	}

	// Start the UDP server!
	log.WithFields(log.Fields{
		"address":        config.UDPAddr,
		"flush_interval": config.Interval,
		"expiry":         config.Expiry,
	}).Info("UDP server listening")
	serverAddr, err := net.ResolveUDPAddr("udp", config.UDPAddr)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Error resolving address")
	}

	serverConn, err := net.ListenUDP("udp", serverAddr)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Error listening for UDP")
	}
	serverConn.SetReadBuffer(1048576 * 4)

	defer serverConn.Close()

	ticker := time.NewTicker(config.Interval)
	go func() {
		for t := range ticker.C {
			metrics := make([][]DDMetric, config.NumWorkers)
			flushTime := time.Now()
			for i, w := range workers {
				log.WithFields(log.Fields{
					"worker": i,
					"tick":   t,
				}).Debug("Flushing")
				wstart := time.Now()
				metrics = append(metrics, w.Flush(config.Interval, config.Expiry, flushTime))
				// Track how much time each worker takes to flush.
				stats.TimeInMilliseconds(
					"flush.worker_duration_ns",
					float64(time.Now().Sub(wstart).Nanoseconds()),
					[]string{fmt.Sprintf("worker:%d", i)},
					1.0,
				)
			}
			fstart := time.Now()
			flush(config, metrics, stats)
			stats.TimeInMilliseconds(
				"flush.transaction_duration_ns",
				float64(time.Now().Sub(fstart).Nanoseconds()),
				nil,
				1.0,
			)
		}
	}()

	buf := make([]byte, config.BufferSize)

	for {
		n, _, err := serverConn.ReadFromUDP(buf)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err,
			}).Error("Error reading from UDP")
			continue
		}
		packet := make([]byte, n)
		copy(packet, buf[:n])
		go handlePacket(config, workers, packet, n, stats)
	}
}

func handlePacket(config *VeneurConfig, workers []*Worker, packet []byte, rlen int, stats *statsd.Client) {
	pstart := time.Now()
	// We could maybe free up the Read above by moving
	// this part to a buffered channel?
	m, err := ParseMetric(packet[:rlen], config.Tags)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Error parsing packet")
		stats.Count("packet.error_total", 1, nil, 1.0)
		return
	}

	stats.TimeInMilliseconds(
		"packet.parse_duration_ns",
		float64(time.Now().Sub(pstart).Nanoseconds()),
		[]string{fmt.Sprintf("type:%s", m.Type)},
		config.SampleRate,
	)

	// Hash the incoming key so we can consistently choose a worker
	// by modding the last byte
	h := fnv.New32()
	h.Write([]byte(m.Name))
	index := h.Sum32() % uint32(config.NumWorkers)

	// We're ready to have a worker process this packet, so add it
	// to the work queue. Note that if the queue is full, we'll block
	// here.
	workers[index].WorkChan <- *m
}

// Flush takes the slices of metrics, combines then and marshals them to json
// for posting to Datadog.
func flush(config *VeneurConfig, postMetrics [][]DDMetric, stats *statsd.Client) {
	totalCount := 0
	var finalMetrics []DDMetric
	// TODO This seems very inefficient
	for _, metrics := range postMetrics {
		totalCount += len(metrics)
		finalMetrics = append(finalMetrics, metrics...)
	}
	// Check to see if we have anything to do
	if totalCount > 0 {
		stats.Count("flush.metrics_total", int64(totalCount), nil, 1.0)
		// TODO Watch this error
		postJSON, _ := json.Marshal(map[string][]DDMetric{
			"series": finalMetrics,
		})

		resp, err := http.Post(fmt.Sprintf("%s/api/v1/series?api_key=%s", config.APIHostname, config.Key), "application/json", bytes.NewBuffer(postJSON))
		if err != nil {
			stats.Count("flush.error_total", int64(totalCount), nil, 1.0)
			// TODO Do something at failure time!
			log.WithFields(log.Fields{
				"error": err,
			}).Error("Error posting")
		} else {
			log.WithFields(log.Fields{
				"metrics": len(finalMetrics),
			}).Info("Completed flush to Datadog")
		}
		if log.GetLevel() == log.DebugLevel {
			defer resp.Body.Close()
			// TODO Watch this error
			body, _ := ioutil.ReadAll(resp.Body)
			log.WithFields(log.Fields{
				"json":     string(postJSON),
				"status":   resp.Status,
				"headers":  resp.Header,
				"response": body,
			}).Debug("POSTing JSON")
		}
	} else {
		log.Info("Nothing to flush, skipping.")
	}
}
<commit_msg>Fix layout<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"hash/fnv"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	statsd "github.com/DataDog/datadog-go/statsd"
	log "github.com/Sirupsen/logrus"
	"github.com/gphat/veneur"
)

var (
	configFile = flag.String("f", "", "The config file to read for settings.")
)

func main() {
	flag.Parse()

	if configFile == nil || *configFile == "" {
		log.Fatal("You must specify a config file")
	}

	config, err := veneur.ReadConfig(*configFile)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Error reading config file")
	}

	// Parse the command-line flags.
	flag.Parse()

	if config.Debug {
		log.SetLevel(log.DebugLevel)
		log.WithFields(log.Fields{
			"config": config,
		}).Debug("Starting with config")
	}

	stats, err := statsd.New(config.StatsAddr)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Error creating statsd logging")
	}
	stats.Namespace = "veneur."

	// Start the dispatcher.
	log.WithFields(log.Fields{
		"number": config.NumWorkers,
	}).Info("Starting workers")
	workers := make([]*veneur.Worker, config.NumWorkers)
	for i := 0; i < config.NumWorkers; i++ {
		worker := veneur.NewWorker(i+1, config)
		worker.Start()
		workers[i] = worker
	}

	// Start the UDP server!
	log.WithFields(log.Fields{
		"address":        config.UDPAddr,
		"flush_interval": config.Interval,
		"expiry":         config.Expiry,
	}).Info("UDP server listening")
	serverAddr, err := net.ResolveUDPAddr("udp", config.UDPAddr)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Error resolving address")
	}

	serverConn, err := net.ListenUDP("udp", serverAddr)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Error listening for UDP")
	}
	serverConn.SetReadBuffer(1048576 * 4)

	defer serverConn.Close()

	ticker := time.NewTicker(config.Interval)
	go func() {
		for t := range ticker.C {
			metrics := make([][]veneur.DDMetric, config.NumWorkers)
			flushTime := time.Now()
			for i, w := range workers {
				log.WithFields(log.Fields{
					"worker": i,
					"tick":   t,
				}).Debug("Flushing")
				wstart := time.Now()
				metrics = append(metrics, w.Flush(config.Interval, config.Expiry, flushTime))
				// Track how much time each worker takes to flush.
				stats.TimeInMilliseconds(
					"flush.worker_duration_ns",
					float64(time.Now().Sub(wstart).Nanoseconds()),
					[]string{fmt.Sprintf("worker:%d", i)},
					1.0,
				)
			}
			fstart := time.Now()
			flush(config, metrics, stats)
			stats.TimeInMilliseconds(
				"flush.transaction_duration_ns",
				float64(time.Now().Sub(fstart).Nanoseconds()),
				nil,
				1.0,
			)
		}
	}()

	buf := make([]byte, config.BufferSize)

	for {
		n, _, err := serverConn.ReadFromUDP(buf)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err,
			}).Error("Error reading from UDP")
			continue
		}
		packet := make([]byte, n)
		copy(packet, buf[:n])
		go handlePacket(config, workers, packet, n, stats)
	}
}

func handlePacket(config *veneur.VeneurConfig, workers []*veneur.Worker, packet []byte, rlen int, stats *statsd.Client) {
	pstart := time.Now()
	// We could maybe free up the Read above by moving
	// this part to a buffered channel?
	m, err := veneur.ParseMetric(packet[:rlen], config.Tags)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Error parsing packet")
		stats.Count("packet.error_total", 1, nil, 1.0)
		return
	}

	stats.TimeInMilliseconds(
		"packet.parse_duration_ns",
		float64(time.Now().Sub(pstart).Nanoseconds()),
		[]string{fmt.Sprintf("type:%s", m.Type)},
		config.SampleRate,
	)

	// Hash the incoming key so we can consistently choose a worker
	// by modding the last byte
	h := fnv.New32()
	h.Write([]byte(m.Name))
	index := h.Sum32() % uint32(config.NumWorkers)

	// We're ready to have a worker process this packet, so add it
	// to the work queue. Note that if the queue is full, we'll block
	// here.
	workers[index].WorkChan <- *m
}

// Flush takes the slices of metrics, combines then and marshals them to json
// for posting to Datadog.
func flush(config *veneur.VeneurConfig, postMetrics [][]veneur.DDMetric, stats *statsd.Client) {
	totalCount := 0
	var finalMetrics []veneur.DDMetric
	// TODO This seems very inefficient
	for _, metrics := range postMetrics {
		totalCount += len(metrics)
		finalMetrics = append(finalMetrics, metrics...)
	}
	// Check to see if we have anything to do
	if totalCount > 0 {
		stats.Count("flush.metrics_total", int64(totalCount), nil, 1.0)
		// TODO Watch this error
		postJSON, _ := json.Marshal(map[string][]veneur.DDMetric{
			"series": finalMetrics,
		})

		resp, err := http.Post(fmt.Sprintf("%s/api/v1/series?api_key=%s", config.APIHostname, config.Key), "application/json", bytes.NewBuffer(postJSON))
		if err != nil {
			stats.Count("flush.error_total", int64(totalCount), nil, 1.0)
			// TODO Do something at failure time!
			log.WithFields(log.Fields{
				"error": err,
			}).Error("Error posting")
		} else {
			log.WithFields(log.Fields{
				"metrics": len(finalMetrics),
			}).Info("Completed flush to Datadog")
		}
		if log.GetLevel() == log.DebugLevel {
			defer resp.Body.Close()
			// TODO Watch this error
			body, _ := ioutil.ReadAll(resp.Body)
			log.WithFields(log.Fields{
				"json":     string(postJSON),
				"status":   resp.Status,
				"headers":  resp.Header,
				"response": body,
			}).Debug("POSTing JSON")
		}
	} else {
		log.Info("Nothing to flush, skipping.")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/zclconf/go-zcl/zclwrite"
)

const versionStr = "0.0.1-dev"

var (
	overwrite   = flag.Bool("w", false, "overwrite source files instead of writing to stdout")
	showVersion = flag.Bool("version", false, "show the version number and immediately exit")
)

func main() {
	if err := realmain(); err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
}

func realmain() error {
	flag.Usage = usage
	flag.Parse()

	if *showVersion {
		fmt.Println(versionStr)
		return nil
	}

	if flag.NArg() == 0 {
		if *overwrite {
			return errors.New("error: cannot use -w without source filenames")
		}

		return processFile("<stdin>", os.Stdin)
	}

	for i := 0; i < flag.NArg(); i++ {
		path := flag.Arg(i)
		switch dir, err := os.Stat(path); {
		case err != nil:
			return err
		case dir.IsDir():
			// This tool can't walk a whole directory because it doesn't
			// know what file naming schemes will be used by different
			// zcl-embedding applications, so it'll leave that sort of
			// functionality for apps themselves to implement.
			return fmt.Errorf("can't format directory %s", path)
		default:
			if err := processFile(path, nil); err != nil {
				return err
			}
		}
	}

	return nil
}

func processFile(fn string, in *os.File) error {
	var err error
	if in == nil {
		in, err = os.Open(fn)
		if err != nil {
			return fmt.Errorf("failed to open %s: %s", fn, err)
		}
	}

	inSrc, err := ioutil.ReadAll(in)
	if err != nil {
		return fmt.Errorf("failed to read %s: %s", fn, err)
	}

	outSrc := zclwrite.Format(inSrc)

	if *overwrite {
		return ioutil.WriteFile(fn, outSrc, 0644)
	}

	_, err = os.Stdout.Write(outSrc)
	return err
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: zclfmt [flags] [path ...]\n")
	flag.PrintDefaults()
	os.Exit(2)
}
<commit_msg>cmd/zclfmt: new options for checking validity of input files<commit_after>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/zclconf/go-zcl/zcl"
	"github.com/zclconf/go-zcl/zclparse"
	"github.com/zclconf/go-zcl/zclwrite"
	"golang.org/x/crypto/ssh/terminal"
)

const versionStr = "0.0.1-dev"

var (
	check       = flag.Bool("check", false, "perform a syntax check on the given files and produce diagnostics")
	reqNoChange = flag.Bool("require-no-change", false, "return a non-zero status if any files are changed during formatting")
	overwrite   = flag.Bool("w", false, "overwrite source files instead of writing to stdout")
	showVersion = flag.Bool("version", false, "show the version number and immediately exit")
)

var parser = zclparse.NewParser()
var diagWr zcl.DiagnosticWriter // initialized in init
var checkErrs = false
var changed []string

func init() {
	color := terminal.IsTerminal(int(os.Stderr.Fd()))
	w, _, err := terminal.GetSize(int(os.Stdout.Fd()))
	if err != nil {
		w = 80
	}
	diagWr = zcl.NewDiagnosticTextWriter(os.Stderr, parser.Files(), uint(w), color)
}

func main() {
	err := realmain()

	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
}

func realmain() error {
	flag.Usage = usage
	flag.Parse()

	if *showVersion {
		fmt.Println(versionStr)
		return nil
	}

	err := processFiles()
	if err != nil {
		return err
	}

	if checkErrs {
		return errors.New("one or more files contained errors")
	}

	if *reqNoChange {
		if len(changed) != 0 {
			return fmt.Errorf("file(s) were changed: %s", strings.Join(changed, ", "))
		}
	}

	return nil
}

func processFiles() error {
	if flag.NArg() == 0 {
		if *overwrite {
			return errors.New("error: cannot use -w without source filenames")
		}

		return processFile("<stdin>", os.Stdin)
	}

	for i := 0; i < flag.NArg(); i++ {
		path := flag.Arg(i)
		switch dir, err := os.Stat(path); {
		case err != nil:
			return err
		case dir.IsDir():
			// This tool can't walk a whole directory because it doesn't
			// know what file naming schemes will be used by different
			// zcl-embedding applications, so it'll leave that sort of
			// functionality for apps themselves to implement.
			return fmt.Errorf("can't format directory %s", path)
		default:
			if err := processFile(path, nil); err != nil {
				return err
			}
		}
	}

	return nil
}

func processFile(fn string, in *os.File) error {
	var err error
	if in == nil {
		in, err = os.Open(fn)
		if err != nil {
			return fmt.Errorf("failed to open %s: %s", fn, err)
		}
	}

	inSrc, err := ioutil.ReadAll(in)
	if err != nil {
		return fmt.Errorf("failed to read %s: %s", fn, err)
	}

	if *check {
		_, diags := parser.ParseZCL(inSrc, fn)
		diagWr.WriteDiagnostics(diags)
		if diags.HasErrors() {
			checkErrs = true
		}
		return nil
	}

	outSrc := zclwrite.Format(inSrc)

	if !bytes.Equal(inSrc, outSrc) {
		changed = append(changed, fn)
	}

	if *overwrite {
		return ioutil.WriteFile(fn, outSrc, 0644)
	}

	_, err = os.Stdout.Write(outSrc)
	return err
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: zclfmt [flags] [path ...]\n")
	flag.PrintDefaults()
	os.Exit(2)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes 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

    http://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.
*/

package cluster

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/pkg/errors"
	"sigs.k8s.io/kind/pkg/cluster/constants"
	"sigs.k8s.io/kind/pkg/cluster/nodes"
	"sigs.k8s.io/kind/pkg/container/docker"
	"sigs.k8s.io/kind/pkg/exec"
)

// CreateExternalEtcd creates a docker container mocking a kind external etcd node
// this is temporary and should go away as soon as kind support external etcd node
func CreateExternalEtcd(name, nodeImage string) (ip string, err error) {
	// define name and labels mocking a kind external etcd node

	containerName := fmt.Sprintf("%s-%s", name, constants.ExternalEtcdNodeRoleValue)

	runArgs := []string{
		"-d",                        // run the container detached
		"--hostname", containerName, // make hostname match container name
		"--name", containerName, // ... and set the container name
		// label the node with the cluster ID
		"--label", fmt.Sprintf("%s=%s", constants.ClusterLabelKey, name),
		// label the node with the role ID
		"--label", fmt.Sprintf("%s=%s", constants.NodeRoleKey, constants.ExternalEtcdNodeRoleValue),
	}

	// define a minimal etcd (insecure, single node, not exposed to the host machine)
	containerArgs := []string{
		"etcd",
		"--name", fmt.Sprintf("%s-etcd", name),
		"--advertise-client-urls", "http://127.0.0.1:2379",
		"--listen-client-urls", "http://0.0.0.0:2379",
	}

	// create a temporary container from the node-image to be able to fetch the etcd version from kubeadm
	_, err = docker.Run(
		nodeImage,
		docker.WithRunArgs("-d", fmt.Sprintf("--name=%s", containerName)),
	)
	if err != nil {
		return "", errors.Wrap(err, "failed to create a temporary node container")
	}
	var etcdVersionBuf bytes.Buffer
	cmder := docker.ContainerCmder(containerName)
	cmd := cmder.Command("/bin/sh", "-c", "kubeadm config images list | grep etcd")
	cmd.SetStdout(&etcdVersionBuf)
	if err := cmd.Run(); err != nil {
		return "", errors.Wrap(err, "failed to get etcd version from the temporary node container")
	}
	if err := exec.Command("docker", "rm", "-f", "-v", containerName).Run(); err != nil {
		return "", errors.Wrap(err, "failed to remove the temporary node container")
	}

	// pull the image if needed
	etcdImage := strings.TrimSpace(etcdVersionBuf.String())
	if _, err := docker.PullIfNotPresent(etcdImage, 2); err != nil {
		return "", errors.Wrap(err, "failed to pre-pull the etcd image")
	}

	// create the etcd container
	_, err = docker.Run(
		etcdImage,
		docker.WithRunArgs(runArgs...),
		docker.WithContainerArgs(containerArgs...),
	)
	if err != nil {
		return "", errors.Wrap(err, "failed to create external etcd container")
	}

	kn, err := NewKNode(*nodes.FromName(containerName))
	if err != nil {
		return "", errors.Wrap(err, "failed to create external etcd node")
	}

	return kn.IP()
}
<commit_msg>kinder: avoid polution of the output of "kubeadm config images list"<commit_after>/*
Copyright 2019 The Kubernetes 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

    http://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.
*/

package cluster

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/pkg/errors"
	"sigs.k8s.io/kind/pkg/cluster/constants"
	"sigs.k8s.io/kind/pkg/cluster/nodes"
	"sigs.k8s.io/kind/pkg/container/docker"
	"sigs.k8s.io/kind/pkg/exec"
)

// CreateExternalEtcd creates a docker container mocking a kind external etcd node
// this is temporary and should go away as soon as kind support external etcd node
func CreateExternalEtcd(name, nodeImage string) (ip string, err error) {
	// define name and labels mocking a kind external etcd node

	containerName := fmt.Sprintf("%s-%s", name, constants.ExternalEtcdNodeRoleValue)

	runArgs := []string{
		"-d",                        // run the container detached
		"--hostname", containerName, // make hostname match container name
		"--name", containerName, // ... and set the container name
		// label the node with the cluster ID
		"--label", fmt.Sprintf("%s=%s", constants.ClusterLabelKey, name),
		// label the node with the role ID
		"--label", fmt.Sprintf("%s=%s", constants.NodeRoleKey, constants.ExternalEtcdNodeRoleValue),
	}

	// define a minimal etcd (insecure, single node, not exposed to the host machine)
	containerArgs := []string{
		"etcd",
		"--name", fmt.Sprintf("%s-etcd", name),
		"--advertise-client-urls", "http://127.0.0.1:2379",
		"--listen-client-urls", "http://0.0.0.0:2379",
	}

	// create a temporary container from the node-image to be able to fetch the etcd version from kubeadm
	_, err = docker.Run(
		nodeImage,
		docker.WithRunArgs("-d", fmt.Sprintf("--name=%s", containerName)),
	)
	if err != nil {
		return "", errors.Wrap(err, "failed to create a temporary node container")
	}
	var etcdVersionBuf bytes.Buffer
	cmder := docker.ContainerCmder(containerName)
	cmd := cmder.Command("/bin/sh", "-c", "kubeadm config images list 2> /dev/null | grep etcd")
	cmd.SetStdout(&etcdVersionBuf)
	if err := cmd.Run(); err != nil {
		return "", errors.Wrap(err, "failed to get etcd version from the temporary node container")
	}
	if err := exec.Command("docker", "rm", "-f", "-v", containerName).Run(); err != nil {
		return "", errors.Wrap(err, "failed to remove the temporary node container")
	}

	// pull the image if needed
	etcdImage := strings.TrimSpace(etcdVersionBuf.String())
	if _, err := docker.PullIfNotPresent(etcdImage, 2); err != nil {
		return "", errors.Wrap(err, "failed to pre-pull the etcd image")
	}

	// create the etcd container
	_, err = docker.Run(
		etcdImage,
		docker.WithRunArgs(runArgs...),
		docker.WithContainerArgs(containerArgs...),
	)
	if err != nil {
		return "", errors.Wrap(err, "failed to create external etcd container")
	}

	kn, err := NewKNode(*nodes.FromName(containerName))
	if err != nil {
		return "", errors.Wrap(err, "failed to create external etcd node")
	}

	return kn.IP()
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Nan Deng
 *
 * 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
 *
 *     http://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.
 *
 */

package rpc

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"time"
)

const (
	SEND_MESSAGE_PATH    = "/send.json"
	FORWARD_MESSAGE_PATH = "/fwd.json"
)

type UniqushConnPeer interface {
	Send(req *SendRequest) *Result
	Forward(req *ForwardRequest) *Result
	Id() string
}

type UniqushConnInstance struct {
	Addr    string        `json:"addr"`
	Timeout time.Duration `json:"timeout,omitempty"`
}

func NewUniqushConnInstance(u *url.URL, timeout time.Duration) (instance *UniqushConnInstance, err error) {
	if u.Scheme != "http" && u.Scheme != "https" {
		return nil, fmt.Errorf("%v is not supported", u.Scheme)
	}
	instance = new(UniqushConnInstance)
	if timeout < 3*time.Second {
		timeout = 3 * time.Second
	}
	instance.Timeout = timeout
	instance.Addr = u.String()
	return
}

func (self *UniqushConnInstance) Id() string {
	return self.Addr
}

func timeoutDialler(ns time.Duration) func(net, addr string) (c net.Conn, err error) {
	return func(netw, addr string) (net.Conn, error) {
		c, err := net.Dial(netw, addr)
		if err != nil {
			return nil, err
		}
		if ns.Seconds() > 0.0 {
			c.SetDeadline(time.Now().Add(ns))
		}
		return c, nil
	}
}

func (self *UniqushConnInstance) post(url string, data interface{}, out interface{}) int {
	if len(url) == 0 || url == "none" {
		return 400
	}
	jdata, err := json.Marshal(data)
	if err != nil {
		return 400
	}
	c := http.Client{
		Transport: &http.Transport{
			Dial: timeoutDialler(self.Timeout),
		},
	}
	resp, err := c.Post(url, "application/json", bytes.NewReader(jdata))
	if err != nil {
		return 400
	}
	defer resp.Body.Close()

	if out != nil {
		e := json.NewDecoder(resp.Body)
		err = e.Decode(out)
		if err != nil {
			return 400
		}
	}
	return resp.StatusCode
}

func (self *UniqushConnInstance) requestThenResult(path string, req interface{}) *Result {
	result := new(Result)
	status := self.post(self.Addr+path, req, result)
	if status != 200 {
		return nil
	}
	return result
}

func (self *UniqushConnInstance) Send(req *SendRequest) *Result {
	return self.requestThenResult(SEND_MESSAGE_PATH, req)
}

func (self *UniqushConnInstance) Forward(req *ForwardRequest) *Result {
	return self.requestThenResult(FORWARD_MESSAGE_PATH, req)
}
<commit_msg>added redirect function for peer. fixing #9<commit_after>/*
 * Copyright 2012 Nan Deng
 *
 * 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
 *
 *     http://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.
 *
 */

package rpc

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"time"
)

const (
	SEND_MESSAGE_PATH    = "/send.json"
	FORWARD_MESSAGE_PATH = "/fwd.json"
	REDIRECT_CLIENT_PATH = "/redir.json"
)

type UniqushConnPeer interface {
	Send(req *SendRequest) *Result
	Forward(req *ForwardRequest) *Result
	Redirect(req *RedirectRequest) *Result
	Id() string
}

type UniqushConnInstance struct {
	Addr    string        `json:"addr"`
	Timeout time.Duration `json:"timeout,omitempty"`
}

func NewUniqushConnInstance(u *url.URL, timeout time.Duration) (instance *UniqushConnInstance, err error) {
	if u.Scheme != "http" && u.Scheme != "https" {
		return nil, fmt.Errorf("%v is not supported", u.Scheme)
	}
	instance = new(UniqushConnInstance)
	if timeout < 3*time.Second {
		timeout = 3 * time.Second
	}
	instance.Timeout = timeout
	instance.Addr = u.String()
	return
}

func (self *UniqushConnInstance) Id() string {
	return self.Addr
}

func timeoutDialler(ns time.Duration) func(net, addr string) (c net.Conn, err error) {
	return func(netw, addr string) (net.Conn, error) {
		c, err := net.Dial(netw, addr)
		if err != nil {
			return nil, err
		}
		if ns.Seconds() > 0.0 {
			c.SetDeadline(time.Now().Add(ns))
		}
		return c, nil
	}
}

func (self *UniqushConnInstance) post(url string, data interface{}, out interface{}) int {
	if len(url) == 0 || url == "none" {
		return 400
	}
	jdata, err := json.Marshal(data)
	if err != nil {
		return 400
	}
	c := http.Client{
		Transport: &http.Transport{
			Dial: timeoutDialler(self.Timeout),
		},
	}
	resp, err := c.Post(url, "application/json", bytes.NewReader(jdata))
	if err != nil {
		return 400
	}
	defer resp.Body.Close()

	if out != nil {
		e := json.NewDecoder(resp.Body)
		err = e.Decode(out)
		if err != nil {
			return 400
		}
	}
	return resp.StatusCode
}

func (self *UniqushConnInstance) requestThenResult(path string, req interface{}) *Result {
	result := new(Result)
	status := self.post(self.Addr+path, req, result)
	if status != 200 {
		return nil
	}
	return result
}

func (self *UniqushConnInstance) Send(req *SendRequest) *Result {
	return self.requestThenResult(SEND_MESSAGE_PATH, req)
}

func (self *UniqushConnInstance) Forward(req *ForwardRequest) *Result {
	return self.requestThenResult(FORWARD_MESSAGE_PATH, req)
}

func (self *UniqushConnInstance) Redirect(req *RedirectRequest) *Result {
	return self.requestThenResult(REDIRECT_CLIENT_PATH, req)
}
<|endoftext|>


<commit_before>package rrd

import (
	"fmt"
	"io/ioutil"
	"testing"
	"time"
)

func TestAll(t *testing.T) {
	// Create
	const (
		dbfile    = "/tmp/test.rrd"
		step      = 1
		heartbeat = 2 * step
	)
	c := NewCreator(dbfile, time.Now(), step)
	c.RRA("AVERAGE", 0.5, 1, 100)
	c.RRA("AVERAGE", 0.5, 5, 100)
	c.DS("cnt", "COUNTER", heartbeat, 0, 100)
	c.DS("g", "GAUGE", heartbeat, 0, 60)
	err := c.Create(true)
	if err != nil {
		t.Fatal(err)
	}

	// Update
	u := NewUpdater(dbfile)
	for i := 0; i < 10; i++ {
		time.Sleep(step * time.Second)
		err := u.Update(time.Now(), i, 1.5*float64(i))
		if err != nil {
			t.Fatal(err)
		}
	}

	// Update with cache
	for i := 10; i < 20; i++ {
		time.Sleep(step * time.Second)
		u.Cache(time.Now(), i, 2*float64(i))
	}
	err = u.Update()
	if err != nil {
		t.Fatal(err)
	}

	// Info
	inf, err := Info(dbfile)
	if err != nil {
		t.Fatal(err)
	}
	for k, v := range inf {
		fmt.Printf("%s: %v\n", k, v)
	}

	// Graph
	g := NewGrapher()
	g.SetTitle("Test")
	g.SetVLabel("some variable")
	g.SetSize(800, 300)
	g.Def("v1", dbfile, "g", "AVERAGE")
	g.Def("v2", dbfile, "cnt", "AVERAGE")
	g.VDef("max1", "v1,MAXIMUM")
	g.VDef("avg2", "v2,AVERAGE")
	g.Line(1, "v1", "ff0000", "var 1")
	g.Area("v2", "0000ff", "var 2")
	g.GPrintT("max1", "max1 at %c")
	g.GPrint("avg2", "avg2=%lf")
	g.PrintT("max1", "max1 at %c")
	g.Print("avg2", "avg2=%lf")
	now := time.Now()

	i, err := g.SaveGraph("/tmp/test_rrd1.png", now.Add(-20*time.Second), now)
	fmt.Printf("%+v\n", i)
	if err != nil {
		t.Fatal(err)
	}
	i, buf, err := g.Graph(now.Add(-20*time.Second), now)
	fmt.Printf("%+v\n", i)
	if err != nil {
		t.Fatal(err)
	}
	err = ioutil.WriteFile("/tmp/test_rrd2.png", buf, 0666)
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>use new watermark option in test<commit_after>package rrd

import (
	"fmt"
	"io/ioutil"
	"testing"
	"time"
)

func TestAll(t *testing.T) {
	// Create
	const (
		dbfile    = "/tmp/test.rrd"
		step      = 1
		heartbeat = 2 * step
	)
	c := NewCreator(dbfile, time.Now(), step)
	c.RRA("AVERAGE", 0.5, 1, 100)
	c.RRA("AVERAGE", 0.5, 5, 100)
	c.DS("cnt", "COUNTER", heartbeat, 0, 100)
	c.DS("g", "GAUGE", heartbeat, 0, 60)
	err := c.Create(true)
	if err != nil {
		t.Fatal(err)
	}

	// Update
	u := NewUpdater(dbfile)
	for i := 0; i < 10; i++ {
		time.Sleep(step * time.Second)
		err := u.Update(time.Now(), i, 1.5*float64(i))
		if err != nil {
			t.Fatal(err)
		}
	}

	// Update with cache
	for i := 10; i < 20; i++ {
		time.Sleep(step * time.Second)
		u.Cache(time.Now(), i, 2*float64(i))
	}
	err = u.Update()
	if err != nil {
		t.Fatal(err)
	}

	// Info
	inf, err := Info(dbfile)
	if err != nil {
		t.Fatal(err)
	}
	for k, v := range inf {
		fmt.Printf("%s: %v\n", k, v)
	}

	// Graph
	g := NewGrapher()
	g.SetTitle("Test")
	g.SetVLabel("some variable")
	g.SetSize(800, 300)
	g.SetWatermark("some watermark")
	g.Def("v1", dbfile, "g", "AVERAGE")
	g.Def("v2", dbfile, "cnt", "AVERAGE")
	g.VDef("max1", "v1,MAXIMUM")
	g.VDef("avg2", "v2,AVERAGE")
	g.Line(1, "v1", "ff0000", "var 1")
	g.Area("v2", "0000ff", "var 2")
	g.GPrintT("max1", "max1 at %c")
	g.GPrint("avg2", "avg2=%lf")
	g.PrintT("max1", "max1 at %c")
	g.Print("avg2", "avg2=%lf")
	now := time.Now()

	i, err := g.SaveGraph("/tmp/test_rrd1.png", now.Add(-20*time.Second), now)
	fmt.Printf("%+v\n", i)
	if err != nil {
		t.Fatal(err)
	}
	i, buf, err := g.Graph(now.Add(-20*time.Second), now)
	fmt.Printf("%+v\n", i)
	if err != nil {
		t.Fatal(err)
	}
	err = ioutil.WriteFile("/tmp/test_rrd2.png", buf, 0666)
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Microsoft. All rights reserved.
// MIT License

package main

import (
	"fmt"

	"github.com/Azure/azure-container-networking/cni"
	"github.com/Azure/azure-container-networking/cni/ipam"
	"github.com/Azure/azure-container-networking/cni/network"
	"github.com/Azure/azure-container-networking/common"
	"github.com/Azure/azure-container-networking/log"
	"github.com/Azure/azure-container-networking/platform"
	"github.com/Azure/azure-container-networking/store"

	cniSkel "github.com/containernetworking/cni/pkg/skel"
	cniVers "github.com/containernetworking/cni/pkg/version"
)

const (
	// Plugin name.
	name = "azure-vnet"
)

// Version is populated by make during build.
var version string

// Main is the entry point for CNI plugin.
func main() {
	// Initialize plugin common configuration.
	var config common.PluginConfig
	config.Name = name
	config.Version = version

	// Create network plugin.
	netPlugin, err := network.NewPlugin(&config)
	if err != nil {
		fmt.Printf("[cni] Failed to create network plugin, err:%v.\n", err)
		return
	}

	// Create IPAM plugin.
	ipamPlugin, err := ipam.NewPlugin(&config)
	if err != nil {
		fmt.Printf("[cni] Failed to create IPAM plugin, err:%v.\n", err)
		return
	}

	// Create a channel to receive unhandled errors from the plugins.
	config.ErrChan = make(chan error, 1)

	// Create the key value store.
	config.Store, err = store.NewJsonFileStore(platform.RuntimePath + name + ".json")
	if err != nil {
		log.Printf("[cni] Failed to create store, err:%v.", err)
		return
	}

	// Acquire store lock.
	err = config.Store.Lock(true)
	if err != nil {
		log.Printf("[cni] Timed out on locking store, err:%v.", err)
		return
	}

	// Create logging provider.
	log.SetLevel(log.LevelInfo)
	err = log.SetTarget(log.TargetLogfile)
	if err != nil {
		fmt.Printf("[cni] Failed to configure logging, err:%v.\n", err)
		return
	}

	// Log platform information.
	log.Printf("[cni] Plugin enter.")
	log.Printf("Running on %v", platform.GetOSInfo())
	common.LogNetworkInterfaces()

	// Set plugin options.
	ipamPlugin.SetOption(common.OptEnvironment, common.OptEnvironmentAzure)

	// Start plugins.
	if netPlugin != nil {
		err = netPlugin.Start(&config)
		if err != nil {
			fmt.Printf("[cni] Failed to start network plugin, err:%v.\n", err)
			return
		}
	}

	if ipamPlugin != nil {
		err = ipamPlugin.Start(&config)
		if err != nil {
			fmt.Printf("[cni] Failed to start IPAM plugin, err:%v.\n", err)
			return
		}
	}

	// Set supported CNI versions.
	pluginInfo := cniVers.PluginSupports(cni.Version)

	// Parse args and call the appropriate cmd handler.
	cniSkel.PluginMain(netPlugin.Add, netPlugin.Delete, pluginInfo)

	// Cleanup.
	if netPlugin != nil {
		netPlugin.Stop()
	}

	if ipamPlugin != nil {
		ipamPlugin.Stop()
	}

	err = config.Store.Unlock()
	if err != nil {
		log.Printf("[cni] Failed to unlock store, err:%v.", err)
	}

	log.Printf("[cni] Plugin exit.")
}
<commit_msg>Deleted redundant code<commit_after><|endoftext|>


<commit_before>package plugins

import (
	"fmt"

	"golang.org/x/net/context"
)

var (
	ctx     context.Context
	plugins = []plugin{}
)

type plugin struct {
	Key interface{}
	BotMessagePlugin
}

func AddPlugin(key interface{}, val BotMessagePlugin) {
	fmt.Println("insert plugin ", key)
	plugins = append(plugins, plugin{key, val})
}

func DelPlugin(key interface{}) {
	// TODO: 未実装
	panic("未実装")
}

func init() {
	ctx = context.Background()
}

type BotMessagePlugin interface {
	CheckMessage(ctx context.Context, message string) (bool, string)
	DoAction(ctx context.Context, message string) bool
}

func Context() context.Context {
	return ctx
}

func ExecPlugins(ctx context.Context, message string) {
	for _, p := range plugins {
		ok, m := p.CheckMessage(ctx, message)
		if !ok {
			continue
		}

		next := p.DoAction(ctx, m)
		if !next {
			break
		}
	}
}
<commit_msg>stopを実装<commit_after>package plugins

import (
	"fmt"

	"golang.org/x/net/context"
)

var (
	ctx     context.Context
	plugins = []Plugin{}
	stop    = false
)

type Plugin struct {
	Key interface{}
	BotMessagePlugin
}

func (p Plugin) Name() string {
	return fmt.Sprintf("%s", p.Key)
}

func AddPlugin(key interface{}, val BotMessagePlugin) {
	fmt.Println("insert plugin ", key)
	plugins = append(plugins, Plugin{key, val})
}

func DelPlugin(key interface{}) {
	// TODO: 未実装
	panic("未実装")
}

// Stop bot stop
func Stop() {
	stop = true
}

// Start bot start
func Start() {
	stop = false
}

// GetPlugins returns all plugins
func GetPlugins() []Plugin {
	return plugins
}

func init() {
	ctx = context.Background()
}

type BotMessagePlugin interface {
	CheckMessage(ctx context.Context, message string) (bool, string)
	DoAction(ctx context.Context, message string) bool
}

func Context() context.Context {
	return ctx
}

func ExecPlugins(ctx context.Context, message string) {
	if stop {
		return
	}

	for _, p := range plugins {
		ok, m := p.CheckMessage(ctx, message)
		if !ok {
			continue
		}

		next := p.DoAction(ctx, m)
		if !next {
			break
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation.
//
// 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
//
//    http://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.

package api

import (
	log "github.com/Sirupsen/logrus"
	"github.com/fukata/golang-stats-api-handler"
	"github.com/gorilla/mux"
	"github.com/osrg/gobgp/packet"
	"net/http"
	"strconv"
)

const (
	_ = iota
	REQ_NEIGHBOR
	REQ_NEIGHBORS
	REQ_ADJ_RIB_IN
	REQ_ADJ_RIB_OUT
	REQ_LOCAL_RIB
	REQ_NEIGHBOR_SHUTDOWN
	REQ_NEIGHBOR_RESET
	REQ_NEIGHBOR_SOFT_RESET
	REQ_NEIGHBOR_SOFT_RESET_IN
	REQ_NEIGHBOR_SOFT_RESET_OUT
	REQ_NEIGHBOR_ENABLE
	REQ_NEIGHBOR_DISABLE
	REQ_GLOBAL_RIB
)

const (
	BASE_VERSION = "/v1"
	GLOBAL       = "/bgp/global"
	NEIGHBOR     = "/bgp/neighbor"
	NEIGHBORS    = "/bgp/neighbors"

	PARAM_REMOTE_PEER_ADDR = "remotePeerAddr"
	PARAM_SHOW_OBJECT      = "showObject"
	PARAM_OPERATION        = "operation"
	PARAM_ROUTE_FAMILY     = "routeFamily"

	STATS = "/stats"
)

const REST_PORT = 8080

// trigger struct for exchanging information in the rest and peer.
// rest and peer operated at different thread.

type RestRequest struct {
	RequestType int
	RemoteAddr  string
	RouteFamily bgp.RouteFamily
	ResponseCh  chan *RestResponse
	Err         error
}

func NewRestRequest(reqType int, remoteAddr string, rf bgp.RouteFamily) *RestRequest {
	r := &RestRequest{
		RequestType: reqType,
		RouteFamily: rf,
		RemoteAddr:  remoteAddr,
		ResponseCh:  make(chan *RestResponse),
	}
	return r
}

type RestResponse struct {
	ResponseErr error
	Data        []byte
}

func (r *RestResponse) Err() error {
	return r.ResponseErr
}

type RestServer struct {
	port        int
	bgpServerCh chan *RestRequest
}

func NewRestServer(port int, bgpServerCh chan *RestRequest) *RestServer {
	rs := &RestServer{
		port:        port,
		bgpServerCh: bgpServerCh}
	return rs
}

// Main thread of rest service.
// URL than can receive.
//   get state of neighbors.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbors
//   get state of neighbor.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>
//   get adj-rib-in of each neighbor.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/adj-rib-in/<rf>
//   get adj-rib-out of each neighbor.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/adj-rib-out/<rf>
//   get local-rib of each neighbor.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/local-rib/<rf>
func (rs *RestServer) Serve() {
	global := BASE_VERSION + GLOBAL
	neighbor := BASE_VERSION + NEIGHBOR
	neighbors := BASE_VERSION + NEIGHBORS

	r := mux.NewRouter()
	perPeerURL := "/{" + PARAM_REMOTE_PEER_ADDR + "}"
	showObjectURL := "/{" + PARAM_SHOW_OBJECT + "}"
	operationURL := "/{" + PARAM_OPERATION + "}"
	routeFamilyURL := "/{" + PARAM_ROUTE_FAMILY + "}"
	r.HandleFunc(global+showObjectURL+routeFamilyURL, rs.GlobalGET).Methods("GET")
	r.HandleFunc(neighbors, rs.NeighborGET).Methods("GET")
	r.HandleFunc(neighbor+perPeerURL, rs.NeighborGET).Methods("GET")
	r.HandleFunc(neighbor+perPeerURL+showObjectURL+routeFamilyURL, rs.NeighborGET).Methods("GET")
	r.HandleFunc(neighbor+perPeerURL+operationURL, rs.NeighborPOST).Methods("POST")
	r.HandleFunc(neighbor+perPeerURL+operationURL+routeFamilyURL, rs.NeighborPOST).Methods("POST")

	// stats
	r.HandleFunc(STATS, stats_api.Handler).Methods("GET")

	// Handler when not found url
	r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
	http.Handle("/", r)

	http.ListenAndServe(":"+strconv.Itoa(rs.port), nil)

}

func (rs *RestServer) neighbor(w http.ResponseWriter, r *http.Request, reqType int) {
	params := mux.Vars(r)
	remoteAddr, _ := params[PARAM_REMOTE_PEER_ADDR]
	log.Debugf("Look up neighbor with the remote address : %v", remoteAddr)
	var rf bgp.RouteFamily
	routeFamily, ok := params[PARAM_ROUTE_FAMILY]
	if ok {
		switch routeFamily {
		case "ipv4":
			rf = bgp.RF_IPv4_UC
		case "ipv6":
			rf = bgp.RF_IPv6_UC
		case "evpn":
			rf = bgp.RF_EVPN
		default:
			NotFoundHandler(w, r)
		}
	}

	//Send channel of request parameter.
	req := NewRestRequest(reqType, remoteAddr, rf)
	rs.bgpServerCh <- req

	//Wait response
	res := <-req.ResponseCh
	if e := res.Err(); e != nil {
		log.Debug(e.Error())
		http.Error(w, e.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Write(res.Data)
}

func (rs *RestServer) NeighborPOST(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	switch params[PARAM_OPERATION] {
	case "shutdown":
		rs.neighbor(w, r, REQ_NEIGHBOR_SHUTDOWN)
	case "reset":
		rs.neighbor(w, r, REQ_NEIGHBOR_RESET)
	case "softreset":
		rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET)
	case "softresetin":
		rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET_IN)
	case "softresetout":
		rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET_OUT)
	case "enable":
		rs.neighbor(w, r, REQ_NEIGHBOR_ENABLE)
	case "disable":
		rs.neighbor(w, r, REQ_NEIGHBOR_DISABLE)
	default:
		NotFoundHandler(w, r)
	}
}

func (rs *RestServer) NeighborGET(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	if _, ok := params[PARAM_REMOTE_PEER_ADDR]; !ok {
		rs.neighbor(w, r, REQ_NEIGHBORS)
		return
	}

	if showObject, ok := params[PARAM_SHOW_OBJECT]; ok {
		switch showObject {
		case "local-rib":
			rs.neighbor(w, r, REQ_LOCAL_RIB)
		case "adj-rib-in":
			rs.neighbor(w, r, REQ_ADJ_RIB_IN)
		case "adj-rib-out":
			rs.neighbor(w, r, REQ_ADJ_RIB_OUT)
		default:
			NotFoundHandler(w, r)
		}
	} else {
		rs.neighbor(w, r, REQ_NEIGHBOR)
	}
}

func (rs *RestServer) GlobalGET(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	if showObject, ok := params[PARAM_SHOW_OBJECT]; ok {
		switch showObject {
		case "rib":
			rs.neighbor(w, r, REQ_GLOBAL_RIB)
		default:
			NotFoundHandler(w, r)
		}
	}

}

func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
	http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
}
<commit_msg>api: return error for invalid route family table<commit_after>// Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation.
//
// 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
//
//    http://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.

package api

import (
	log "github.com/Sirupsen/logrus"
	"github.com/fukata/golang-stats-api-handler"
	"github.com/gorilla/mux"
	"github.com/osrg/gobgp/packet"
	"net/http"
	"strconv"
)

const (
	_ = iota
	REQ_NEIGHBOR
	REQ_NEIGHBORS
	REQ_ADJ_RIB_IN
	REQ_ADJ_RIB_OUT
	REQ_LOCAL_RIB
	REQ_NEIGHBOR_SHUTDOWN
	REQ_NEIGHBOR_RESET
	REQ_NEIGHBOR_SOFT_RESET
	REQ_NEIGHBOR_SOFT_RESET_IN
	REQ_NEIGHBOR_SOFT_RESET_OUT
	REQ_NEIGHBOR_ENABLE
	REQ_NEIGHBOR_DISABLE
	REQ_GLOBAL_RIB
)

const (
	BASE_VERSION = "/v1"
	GLOBAL       = "/bgp/global"
	NEIGHBOR     = "/bgp/neighbor"
	NEIGHBORS    = "/bgp/neighbors"

	PARAM_REMOTE_PEER_ADDR = "remotePeerAddr"
	PARAM_SHOW_OBJECT      = "showObject"
	PARAM_OPERATION        = "operation"
	PARAM_ROUTE_FAMILY     = "routeFamily"

	STATS = "/stats"
)

const REST_PORT = 8080

// trigger struct for exchanging information in the rest and peer.
// rest and peer operated at different thread.

type RestRequest struct {
	RequestType int
	RemoteAddr  string
	RouteFamily bgp.RouteFamily
	ResponseCh  chan *RestResponse
	Err         error
}

func NewRestRequest(reqType int, remoteAddr string, rf bgp.RouteFamily) *RestRequest {
	r := &RestRequest{
		RequestType: reqType,
		RouteFamily: rf,
		RemoteAddr:  remoteAddr,
		ResponseCh:  make(chan *RestResponse),
	}
	return r
}

type RestResponse struct {
	ResponseErr error
	Data        []byte
}

func (r *RestResponse) Err() error {
	return r.ResponseErr
}

type RestServer struct {
	port        int
	bgpServerCh chan *RestRequest
}

func NewRestServer(port int, bgpServerCh chan *RestRequest) *RestServer {
	rs := &RestServer{
		port:        port,
		bgpServerCh: bgpServerCh}
	return rs
}

// Main thread of rest service.
// URL than can receive.
//   get state of neighbors.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbors
//   get state of neighbor.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>
//   get adj-rib-in of each neighbor.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/adj-rib-in/<rf>
//   get adj-rib-out of each neighbor.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/adj-rib-out/<rf>
//   get local-rib of each neighbor.
//     -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/local-rib/<rf>
func (rs *RestServer) Serve() {
	global := BASE_VERSION + GLOBAL
	neighbor := BASE_VERSION + NEIGHBOR
	neighbors := BASE_VERSION + NEIGHBORS

	r := mux.NewRouter()
	perPeerURL := "/{" + PARAM_REMOTE_PEER_ADDR + "}"
	showObjectURL := "/{" + PARAM_SHOW_OBJECT + "}"
	operationURL := "/{" + PARAM_OPERATION + "}"
	routeFamilyURL := "/{" + PARAM_ROUTE_FAMILY + "}"
	r.HandleFunc(global+showObjectURL+routeFamilyURL, rs.GlobalGET).Methods("GET")
	r.HandleFunc(neighbors, rs.NeighborGET).Methods("GET")
	r.HandleFunc(neighbor+perPeerURL, rs.NeighborGET).Methods("GET")
	r.HandleFunc(neighbor+perPeerURL+showObjectURL+routeFamilyURL, rs.NeighborGET).Methods("GET")
	r.HandleFunc(neighbor+perPeerURL+operationURL, rs.NeighborPOST).Methods("POST")
	r.HandleFunc(neighbor+perPeerURL+operationURL+routeFamilyURL, rs.NeighborPOST).Methods("POST")

	// stats
	r.HandleFunc(STATS, stats_api.Handler).Methods("GET")

	// Handler when not found url
	r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
	http.Handle("/", r)

	http.ListenAndServe(":"+strconv.Itoa(rs.port), nil)

}

func (rs *RestServer) neighbor(w http.ResponseWriter, r *http.Request, reqType int) {
	params := mux.Vars(r)
	remoteAddr, _ := params[PARAM_REMOTE_PEER_ADDR]
	log.Debugf("Look up neighbor with the remote address : %v", remoteAddr)
	var rf bgp.RouteFamily
	routeFamily, ok := params[PARAM_ROUTE_FAMILY]
	if ok {
		switch routeFamily {
		case "ipv4":
			rf = bgp.RF_IPv4_UC
		case "ipv6":
			rf = bgp.RF_IPv6_UC
		case "evpn":
			rf = bgp.RF_EVPN
		default:
			NotFoundHandler(w, r)
			return
		}
	}

	//Send channel of request parameter.
	req := NewRestRequest(reqType, remoteAddr, rf)
	rs.bgpServerCh <- req

	//Wait response
	res := <-req.ResponseCh
	if e := res.Err(); e != nil {
		log.Debug(e.Error())
		http.Error(w, e.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Write(res.Data)
}

func (rs *RestServer) NeighborPOST(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	switch params[PARAM_OPERATION] {
	case "shutdown":
		rs.neighbor(w, r, REQ_NEIGHBOR_SHUTDOWN)
	case "reset":
		rs.neighbor(w, r, REQ_NEIGHBOR_RESET)
	case "softreset":
		rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET)
	case "softresetin":
		rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET_IN)
	case "softresetout":
		rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET_OUT)
	case "enable":
		rs.neighbor(w, r, REQ_NEIGHBOR_ENABLE)
	case "disable":
		rs.neighbor(w, r, REQ_NEIGHBOR_DISABLE)
	default:
		NotFoundHandler(w, r)
	}
}

func (rs *RestServer) NeighborGET(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	if _, ok := params[PARAM_REMOTE_PEER_ADDR]; !ok {
		rs.neighbor(w, r, REQ_NEIGHBORS)
		return
	}

	if showObject, ok := params[PARAM_SHOW_OBJECT]; ok {
		switch showObject {
		case "local-rib":
			rs.neighbor(w, r, REQ_LOCAL_RIB)
		case "adj-rib-in":
			rs.neighbor(w, r, REQ_ADJ_RIB_IN)
		case "adj-rib-out":
			rs.neighbor(w, r, REQ_ADJ_RIB_OUT)
		default:
			NotFoundHandler(w, r)
		}
	} else {
		rs.neighbor(w, r, REQ_NEIGHBOR)
	}
}

func (rs *RestServer) GlobalGET(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	if showObject, ok := params[PARAM_SHOW_OBJECT]; ok {
		switch showObject {
		case "rib":
			rs.neighbor(w, r, REQ_GLOBAL_RIB)
		default:
			NotFoundHandler(w, r)
		}
	}

}

func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
	http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
}
<|endoftext|>


<commit_before>// +build !windows

/*
   Copyright The containerd 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

       http://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.
*/

package oci

import (
	"context"
	"path/filepath"

	"github.com/containerd/containerd/namespaces"
	specs "github.com/opencontainers/runtime-spec/specs-go"
)

const (
	rwm               = "rwm"
	defaultRootfsPath = "rootfs"
)

var (
	defaultEnv = []string{
		"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
	}
)

func defaultCaps() []string {
	return []string{
		"CAP_CHOWN",
		"CAP_DAC_OVERRIDE",
		"CAP_FSETID",
		"CAP_FOWNER",
		"CAP_MKNOD",
		"CAP_NET_RAW",
		"CAP_SETGID",
		"CAP_SETUID",
		"CAP_SETFCAP",
		"CAP_SETPCAP",
		"CAP_NET_BIND_SERVICE",
		"CAP_SYS_CHROOT",
		"CAP_KILL",
		"CAP_AUDIT_WRITE",
	}
}

func defaultNamespaces() []specs.LinuxNamespace {
	return []specs.LinuxNamespace{
		{
			Type: specs.PIDNamespace,
		},
		{
			Type: specs.IPCNamespace,
		},
		{
			Type: specs.UTSNamespace,
		},
		{
			Type: specs.MountNamespace,
		},
		{
			Type: specs.NetworkNamespace,
		},
	}
}

func createDefaultSpec(ctx context.Context, id string) (*Spec, error) {
	ns, err := namespaces.NamespaceRequired(ctx)
	if err != nil {
		return nil, err
	}
	s := &Spec{
		Version: specs.Version,
		Root: &specs.Root{
			Path: defaultRootfsPath,
		},
		Process: &specs.Process{
			Env:             defaultEnv,
			Cwd:             "/",
			NoNewPrivileges: true,
			User: specs.User{
				UID: 0,
				GID: 0,
			},
			Capabilities: &specs.LinuxCapabilities{
				Bounding:    defaultCaps(),
				Permitted:   defaultCaps(),
				Inheritable: defaultCaps(),
				Effective:   defaultCaps(),
			},
			Rlimits: []specs.POSIXRlimit{
				{
					Type: "RLIMIT_NOFILE",
					Hard: uint64(1024),
					Soft: uint64(1024),
				},
			},
		},
		Mounts: []specs.Mount{
			{
				Destination: "/proc",
				Type:        "proc",
				Source:      "proc",
			},
			{
				Destination: "/dev",
				Type:        "tmpfs",
				Source:      "tmpfs",
				Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
			},
			{
				Destination: "/dev/pts",
				Type:        "devpts",
				Source:      "devpts",
				Options:     []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
			},
			{
				Destination: "/dev/shm",
				Type:        "tmpfs",
				Source:      "shm",
				Options:     []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
			},
			{
				Destination: "/dev/mqueue",
				Type:        "mqueue",
				Source:      "mqueue",
				Options:     []string{"nosuid", "noexec", "nodev"},
			},
			{
				Destination: "/sys",
				Type:        "sysfs",
				Source:      "sysfs",
				Options:     []string{"nosuid", "noexec", "nodev", "ro"},
			},
			{
				Destination: "/run",
				Type:        "tmpfs",
				Source:      "tmpfs",
				Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
			},
		},
		Linux: &specs.Linux{
			MaskedPaths: []string{
				"/proc/acpi",
				"/proc/kcore",
				"/proc/latency_stats",
				"/proc/timer_list",
				"/proc/timer_stats",
				"/proc/sched_debug",
				"/sys/firmware",
				"/proc/scsi",
			},
			ReadonlyPaths: []string{
				"/proc/asound",
				"/proc/bus",
				"/proc/fs",
				"/proc/irq",
				"/proc/sys",
				"/proc/sysrq-trigger",
			},
			CgroupsPath: filepath.Join("/", ns, id),
			Resources: &specs.LinuxResources{
				Devices: []specs.LinuxDeviceCgroup{
					{
						Allow:  false,
						Access: rwm,
					},
				},
			},
			Namespaces: defaultNamespaces(),
		},
	}
	return s, nil
}
<commit_msg>Add /proc/keys to masked paths<commit_after>// +build !windows

/*
   Copyright The containerd 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

       http://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.
*/

package oci

import (
	"context"
	"path/filepath"

	"github.com/containerd/containerd/namespaces"
	specs "github.com/opencontainers/runtime-spec/specs-go"
)

const (
	rwm               = "rwm"
	defaultRootfsPath = "rootfs"
)

var (
	defaultEnv = []string{
		"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
	}
)

func defaultCaps() []string {
	return []string{
		"CAP_CHOWN",
		"CAP_DAC_OVERRIDE",
		"CAP_FSETID",
		"CAP_FOWNER",
		"CAP_MKNOD",
		"CAP_NET_RAW",
		"CAP_SETGID",
		"CAP_SETUID",
		"CAP_SETFCAP",
		"CAP_SETPCAP",
		"CAP_NET_BIND_SERVICE",
		"CAP_SYS_CHROOT",
		"CAP_KILL",
		"CAP_AUDIT_WRITE",
	}
}

func defaultNamespaces() []specs.LinuxNamespace {
	return []specs.LinuxNamespace{
		{
			Type: specs.PIDNamespace,
		},
		{
			Type: specs.IPCNamespace,
		},
		{
			Type: specs.UTSNamespace,
		},
		{
			Type: specs.MountNamespace,
		},
		{
			Type: specs.NetworkNamespace,
		},
	}
}

func createDefaultSpec(ctx context.Context, id string) (*Spec, error) {
	ns, err := namespaces.NamespaceRequired(ctx)
	if err != nil {
		return nil, err
	}
	s := &Spec{
		Version: specs.Version,
		Root: &specs.Root{
			Path: defaultRootfsPath,
		},
		Process: &specs.Process{
			Env:             defaultEnv,
			Cwd:             "/",
			NoNewPrivileges: true,
			User: specs.User{
				UID: 0,
				GID: 0,
			},
			Capabilities: &specs.LinuxCapabilities{
				Bounding:    defaultCaps(),
				Permitted:   defaultCaps(),
				Inheritable: defaultCaps(),
				Effective:   defaultCaps(),
			},
			Rlimits: []specs.POSIXRlimit{
				{
					Type: "RLIMIT_NOFILE",
					Hard: uint64(1024),
					Soft: uint64(1024),
				},
			},
		},
		Mounts: []specs.Mount{
			{
				Destination: "/proc",
				Type:        "proc",
				Source:      "proc",
			},
			{
				Destination: "/dev",
				Type:        "tmpfs",
				Source:      "tmpfs",
				Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
			},
			{
				Destination: "/dev/pts",
				Type:        "devpts",
				Source:      "devpts",
				Options:     []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
			},
			{
				Destination: "/dev/shm",
				Type:        "tmpfs",
				Source:      "shm",
				Options:     []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
			},
			{
				Destination: "/dev/mqueue",
				Type:        "mqueue",
				Source:      "mqueue",
				Options:     []string{"nosuid", "noexec", "nodev"},
			},
			{
				Destination: "/sys",
				Type:        "sysfs",
				Source:      "sysfs",
				Options:     []string{"nosuid", "noexec", "nodev", "ro"},
			},
			{
				Destination: "/run",
				Type:        "tmpfs",
				Source:      "tmpfs",
				Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
			},
		},
		Linux: &specs.Linux{
			MaskedPaths: []string{
				"/proc/acpi",
				"/proc/kcore",
				"/proc/keys",
				"/proc/latency_stats",
				"/proc/timer_list",
				"/proc/timer_stats",
				"/proc/sched_debug",
				"/sys/firmware",
				"/proc/scsi",
			},
			ReadonlyPaths: []string{
				"/proc/asound",
				"/proc/bus",
				"/proc/fs",
				"/proc/irq",
				"/proc/sys",
				"/proc/sysrq-trigger",
			},
			CgroupsPath: filepath.Join("/", ns, id),
			Resources: &specs.LinuxResources{
				Devices: []specs.LinuxDeviceCgroup{
					{
						Allow:  false,
						Access: rwm,
					},
				},
			},
			Namespaces: defaultNamespaces(),
		},
	}
	return s, nil
}
<|endoftext|>