<commit_before>// MinIO Cloud Storage, (C) 2015, 2016, 2017, 2018 MinIO, Inc.
//
// 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 crypto

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"strings"
	"time"

	vault "github.com/hashicorp/vault/api"
)

var (
	//ErrKMSAuthLogin is raised when there is a failure authenticating to KMS
	ErrKMSAuthLogin = errors.New("Vault service did not return auth info")
)

// VaultKey represents vault encryption key-ring.
type VaultKey struct {
	Name    string `json:"name"`    // The name of the encryption key-ring
	Version int    `json:"version"` // The key version
}

// VaultAuth represents vault authentication type.
// Currently the only supported authentication type is AppRole.
type VaultAuth struct {
	Type    string       `json:"type"`    // The authentication type
	AppRole VaultAppRole `json:"approle"` // The AppRole authentication credentials
}

// VaultAppRole represents vault AppRole authentication credentials
type VaultAppRole struct {
	ID     string `json:"id"`     // The AppRole access ID
	Secret string `json:"secret"` // The AppRole secret
}

// VaultConfig represents vault configuration.
type VaultConfig struct {
	Endpoint  string    `json:"endpoint"` // The vault API endpoint as URL
	CAPath    string    `json:"-"`        // The path to PEM-encoded certificate files used for mTLS. Currently not used in config file.
	Auth      VaultAuth `json:"auth"`     // The vault authentication configuration
	Key       VaultKey  `json:"key-id"`   // The named key used for key-generation / decryption.
	Namespace string    `json:"-"`        // The vault namespace of enterprise vault instances
}

// vaultService represents a connection to a vault KMS.
type vaultService struct {
	config        *VaultConfig
	client        *vault.Client
	secret        *vault.Secret
	leaseDuration time.Duration
}

var _ KMS = (*vaultService)(nil) // compiler check that *vaultService implements KMS

// empty/default vault configuration used to check whether a particular is empty.
var emptyVaultConfig = VaultConfig{}

// IsEmpty returns true if the vault config struct is an
// empty configuration.
func (v *VaultConfig) IsEmpty() bool { return *v == emptyVaultConfig }

// Verify returns a nil error if the vault configuration
// is valid. A valid configuration is either empty or
// contains valid non-default values.
func (v *VaultConfig) Verify() (err error) {
	if v.IsEmpty() {
		return // an empty configuration is valid
	}
	switch {
	case v.Endpoint == "":
		err = errors.New("crypto: missing hashicorp vault endpoint")
	case strings.ToLower(v.Auth.Type) != "approle":
		err = fmt.Errorf("crypto: invalid hashicorp vault authentication type: %s is not supported", v.Auth.Type)
	case v.Auth.AppRole.ID == "":
		err = errors.New("crypto: missing hashicorp vault AppRole ID")
	case v.Auth.AppRole.Secret == "":
		err = errors.New("crypto: missing hashicorp vault AppSecret ID")
	case v.Key.Name == "":
		err = errors.New("crypto: missing hashicorp vault key name")
	case v.Key.Version < 0:
		err = errors.New("crypto: invalid hashicorp vault key version: The key version must not be negative")
	}
	return
}

// NewVault initializes Hashicorp Vault KMS by authenticating
// to Vault with the credentials in config and gets a client
// token for future api calls.
func NewVault(config VaultConfig) (KMS, error) {
	if config.IsEmpty() {
		return nil, errors.New("crypto: the hashicorp vault configuration must not be empty")
	}
	if err := config.Verify(); err != nil {
		return nil, err
	}

	vaultCfg := vault.Config{Address: config.Endpoint}
	if err := vaultCfg.ConfigureTLS(&vault.TLSConfig{CAPath: config.CAPath}); err != nil {
		return nil, err
	}
	client, err := vault.NewClient(&vaultCfg)
	if err != nil {
		return nil, err
	}
	if config.Namespace != "" {
		client.SetNamespace(config.Namespace)
	}
	v := &vaultService{client: client, config: &config}
	if err := v.authenticate(); err != nil {
		return nil, err
	}
	v.renewToken()
	return v, nil
}

// renewToken starts a new go-routine which renews
// the vault authentication token periodically and re-authenticates
// if the token renewal fails
func (v *vaultService) renewToken() {
	retryDelay := v.leaseDuration / 2
	go func() {
		for {
			if v.secret == nil {
				if err := v.authenticate(); err != nil {
					time.Sleep(retryDelay)
					continue
				}
			}
			s, err := v.client.Auth().Token().RenewSelf(int(v.leaseDuration))
			if err != nil || s == nil {
				v.secret = nil
				time.Sleep(retryDelay)
				continue
			}
			if ok, err := s.TokenIsRenewable(); !ok || err != nil {
				v.secret = nil
				continue
			}
			ttl, err := s.TokenTTL()
			if err != nil {
				v.secret = nil
				continue
			}
			v.secret = s
			retryDelay = ttl / 2
			time.Sleep(retryDelay)
		}
	}()
}

// authenticate logs the app to vault, and starts the auto renewer
// before secret expires
func (v *vaultService) authenticate() (err error) {
	payload := map[string]interface{}{
		"role_id":   v.config.Auth.AppRole.ID,
		"secret_id": v.config.Auth.AppRole.Secret,
	}
	var tokenID string
	var ttl time.Duration
	var secret *vault.Secret
	secret, err = v.client.Logical().Write("auth/approle/login", payload)
	if err != nil {
		return
	}
	if secret == nil {
		err = ErrKMSAuthLogin
		return
	}

	tokenID, err = secret.TokenID()
	if err != nil {
		err = ErrKMSAuthLogin
		return
	}
	ttl, err = secret.TokenTTL()
	if err != nil {
		err = ErrKMSAuthLogin
		return
	}
	v.client.SetToken(tokenID)
	v.secret = secret
	v.leaseDuration = ttl
	return
}

// GenerateKey returns a new plaintext key, generated by the KMS,
// and a sealed version of this plaintext key encrypted using the
// named key referenced by keyID. It also binds the generated key
// cryptographically to the provided context.
func (v *vaultService) GenerateKey(keyID string, ctx Context) (key [32]byte, sealedKey []byte, err error) {
	var contextStream bytes.Buffer
	ctx.WriteTo(&contextStream)

	payload := map[string]interface{}{
		"context": base64.StdEncoding.EncodeToString(contextStream.Bytes()),
	}
	s, err := v.client.Logical().Write(fmt.Sprintf("/transit/datakey/plaintext/%s", keyID), payload)
	if err != nil {
		return key, sealedKey, err
	}
	sealKey := s.Data["ciphertext"].(string)
	plainKey, err := base64.StdEncoding.DecodeString(s.Data["plaintext"].(string))
	if err != nil {
		return key, sealedKey, err
	}
	copy(key[:], []byte(plainKey))
	return key, []byte(sealKey), nil
}

// UnsealKey returns the decrypted sealedKey as plaintext key.
// Therefore it sends the sealedKey to the KMS which decrypts
// it using the named key referenced by keyID and responses with
// the plaintext key.
//
// The context must be same context as the one provided while
// generating the plaintext key / sealedKey.
func (v *vaultService) UnsealKey(keyID string, sealedKey []byte, ctx Context) (key [32]byte, err error) {
	var contextStream bytes.Buffer
	ctx.WriteTo(&contextStream)

	payload := map[string]interface{}{
		"ciphertext": string(sealedKey),
		"context":    base64.StdEncoding.EncodeToString(contextStream.Bytes()),
	}
	s, err := v.client.Logical().Write(fmt.Sprintf("/transit/decrypt/%s", keyID), payload)
	if err != nil {
		return key, err
	}
	base64Key := s.Data["plaintext"].(string)
	plainKey, err := base64.StdEncoding.DecodeString(base64Key)
	if err != nil {
		return key, err
	}
	copy(key[:], []byte(plainKey))
	return key, nil
}

// UpdateKey re-wraps the sealedKey if the master key referenced by the keyID
// has been changed by the KMS operator - i.e. the master key has been rotated.
// If the master key hasn't changed since the sealedKey has been created / updated
// it may return the same sealedKey as rotatedKey.
//
// The context must be same context as the one provided while
// generating the plaintext key / sealedKey.
func (v *vaultService) UpdateKey(keyID string, sealedKey []byte, ctx Context) (rotatedKey []byte, err error) {
	var contextStream bytes.Buffer
	ctx.WriteTo(&contextStream)

	payload := map[string]interface{}{
		"ciphertext": string(sealedKey),
		"context":    base64.StdEncoding.EncodeToString(contextStream.Bytes()),
	}
	s, err := v.client.Logical().Write(fmt.Sprintf("/transit/rewrap/%s", keyID), payload)
	if err != nil {
		return nil, err
	}
	ciphertext, ok := s.Data["ciphertext"]
	if !ok {
		return nil, errMissingUpdatedKey
	}
	rotatedKey = ciphertext.([]byte)
	return rotatedKey, nil
}
<commit_msg>fix type conversion in `UpdateKey` for Vault (#8058)<commit_after>// MinIO Cloud Storage, (C) 2015, 2016, 2017, 2018 MinIO, Inc.
//
// 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 crypto

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"strings"
	"time"

	vault "github.com/hashicorp/vault/api"
)

var (
	//ErrKMSAuthLogin is raised when there is a failure authenticating to KMS
	ErrKMSAuthLogin = errors.New("Vault service did not return auth info")
)

// VaultKey represents vault encryption key-ring.
type VaultKey struct {
	Name    string `json:"name"`    // The name of the encryption key-ring
	Version int    `json:"version"` // The key version
}

// VaultAuth represents vault authentication type.
// Currently the only supported authentication type is AppRole.
type VaultAuth struct {
	Type    string       `json:"type"`    // The authentication type
	AppRole VaultAppRole `json:"approle"` // The AppRole authentication credentials
}

// VaultAppRole represents vault AppRole authentication credentials
type VaultAppRole struct {
	ID     string `json:"id"`     // The AppRole access ID
	Secret string `json:"secret"` // The AppRole secret
}

// VaultConfig represents vault configuration.
type VaultConfig struct {
	Endpoint  string    `json:"endpoint"` // The vault API endpoint as URL
	CAPath    string    `json:"-"`        // The path to PEM-encoded certificate files used for mTLS. Currently not used in config file.
	Auth      VaultAuth `json:"auth"`     // The vault authentication configuration
	Key       VaultKey  `json:"key-id"`   // The named key used for key-generation / decryption.
	Namespace string    `json:"-"`        // The vault namespace of enterprise vault instances
}

// vaultService represents a connection to a vault KMS.
type vaultService struct {
	config        *VaultConfig
	client        *vault.Client
	secret        *vault.Secret
	leaseDuration time.Duration
}

var _ KMS = (*vaultService)(nil) // compiler check that *vaultService implements KMS

// empty/default vault configuration used to check whether a particular is empty.
var emptyVaultConfig = VaultConfig{}

// IsEmpty returns true if the vault config struct is an
// empty configuration.
func (v *VaultConfig) IsEmpty() bool { return *v == emptyVaultConfig }

// Verify returns a nil error if the vault configuration
// is valid. A valid configuration is either empty or
// contains valid non-default values.
func (v *VaultConfig) Verify() (err error) {
	if v.IsEmpty() {
		return // an empty configuration is valid
	}
	switch {
	case v.Endpoint == "":
		err = errors.New("crypto: missing hashicorp vault endpoint")
	case strings.ToLower(v.Auth.Type) != "approle":
		err = fmt.Errorf("crypto: invalid hashicorp vault authentication type: %s is not supported", v.Auth.Type)
	case v.Auth.AppRole.ID == "":
		err = errors.New("crypto: missing hashicorp vault AppRole ID")
	case v.Auth.AppRole.Secret == "":
		err = errors.New("crypto: missing hashicorp vault AppSecret ID")
	case v.Key.Name == "":
		err = errors.New("crypto: missing hashicorp vault key name")
	case v.Key.Version < 0:
		err = errors.New("crypto: invalid hashicorp vault key version: The key version must not be negative")
	}
	return
}

// NewVault initializes Hashicorp Vault KMS by authenticating
// to Vault with the credentials in config and gets a client
// token for future api calls.
func NewVault(config VaultConfig) (KMS, error) {
	if config.IsEmpty() {
		return nil, errors.New("crypto: the hashicorp vault configuration must not be empty")
	}
	if err := config.Verify(); err != nil {
		return nil, err
	}

	vaultCfg := vault.Config{Address: config.Endpoint}
	if err := vaultCfg.ConfigureTLS(&vault.TLSConfig{CAPath: config.CAPath}); err != nil {
		return nil, err
	}
	client, err := vault.NewClient(&vaultCfg)
	if err != nil {
		return nil, err
	}
	if config.Namespace != "" {
		client.SetNamespace(config.Namespace)
	}
	v := &vaultService{client: client, config: &config}
	if err := v.authenticate(); err != nil {
		return nil, err
	}
	v.renewToken()
	return v, nil
}

// renewToken starts a new go-routine which renews
// the vault authentication token periodically and re-authenticates
// if the token renewal fails
func (v *vaultService) renewToken() {
	retryDelay := v.leaseDuration / 2
	go func() {
		for {
			if v.secret == nil {
				if err := v.authenticate(); err != nil {
					time.Sleep(retryDelay)
					continue
				}
			}
			s, err := v.client.Auth().Token().RenewSelf(int(v.leaseDuration))
			if err != nil || s == nil {
				v.secret = nil
				time.Sleep(retryDelay)
				continue
			}
			if ok, err := s.TokenIsRenewable(); !ok || err != nil {
				v.secret = nil
				continue
			}
			ttl, err := s.TokenTTL()
			if err != nil {
				v.secret = nil
				continue
			}
			v.secret = s
			retryDelay = ttl / 2
			time.Sleep(retryDelay)
		}
	}()
}

// authenticate logs the app to vault, and starts the auto renewer
// before secret expires
func (v *vaultService) authenticate() (err error) {
	payload := map[string]interface{}{
		"role_id":   v.config.Auth.AppRole.ID,
		"secret_id": v.config.Auth.AppRole.Secret,
	}
	var tokenID string
	var ttl time.Duration
	var secret *vault.Secret
	secret, err = v.client.Logical().Write("auth/approle/login", payload)
	if err != nil {
		return
	}
	if secret == nil {
		err = ErrKMSAuthLogin
		return
	}

	tokenID, err = secret.TokenID()
	if err != nil {
		err = ErrKMSAuthLogin
		return
	}
	ttl, err = secret.TokenTTL()
	if err != nil {
		err = ErrKMSAuthLogin
		return
	}
	v.client.SetToken(tokenID)
	v.secret = secret
	v.leaseDuration = ttl
	return
}

// GenerateKey returns a new plaintext key, generated by the KMS,
// and a sealed version of this plaintext key encrypted using the
// named key referenced by keyID. It also binds the generated key
// cryptographically to the provided context.
func (v *vaultService) GenerateKey(keyID string, ctx Context) (key [32]byte, sealedKey []byte, err error) {
	var contextStream bytes.Buffer
	ctx.WriteTo(&contextStream)

	payload := map[string]interface{}{
		"context": base64.StdEncoding.EncodeToString(contextStream.Bytes()),
	}
	s, err := v.client.Logical().Write(fmt.Sprintf("/transit/datakey/plaintext/%s", keyID), payload)
	if err != nil {
		return key, sealedKey, err
	}
	sealKey := s.Data["ciphertext"].(string)
	plainKey, err := base64.StdEncoding.DecodeString(s.Data["plaintext"].(string))
	if err != nil {
		return key, sealedKey, err
	}
	copy(key[:], []byte(plainKey))
	return key, []byte(sealKey), nil
}

// UnsealKey returns the decrypted sealedKey as plaintext key.
// Therefore it sends the sealedKey to the KMS which decrypts
// it using the named key referenced by keyID and responses with
// the plaintext key.
//
// The context must be same context as the one provided while
// generating the plaintext key / sealedKey.
func (v *vaultService) UnsealKey(keyID string, sealedKey []byte, ctx Context) (key [32]byte, err error) {
	var contextStream bytes.Buffer
	ctx.WriteTo(&contextStream)

	payload := map[string]interface{}{
		"ciphertext": string(sealedKey),
		"context":    base64.StdEncoding.EncodeToString(contextStream.Bytes()),
	}
	s, err := v.client.Logical().Write(fmt.Sprintf("/transit/decrypt/%s", keyID), payload)
	if err != nil {
		return key, err
	}
	base64Key := s.Data["plaintext"].(string)
	plainKey, err := base64.StdEncoding.DecodeString(base64Key)
	if err != nil {
		return key, err
	}
	copy(key[:], []byte(plainKey))
	return key, nil
}

// UpdateKey re-wraps the sealedKey if the master key referenced by the keyID
// has been changed by the KMS operator - i.e. the master key has been rotated.
// If the master key hasn't changed since the sealedKey has been created / updated
// it may return the same sealedKey as rotatedKey.
//
// The context must be same context as the one provided while
// generating the plaintext key / sealedKey.
func (v *vaultService) UpdateKey(keyID string, sealedKey []byte, ctx Context) (rotatedKey []byte, err error) {
	var contextStream bytes.Buffer
	ctx.WriteTo(&contextStream)

	payload := map[string]interface{}{
		"ciphertext": string(sealedKey),
		"context":    base64.StdEncoding.EncodeToString(contextStream.Bytes()),
	}
	s, err := v.client.Logical().Write(fmt.Sprintf("/transit/rewrap/%s", keyID), payload)
	if err != nil {
		return nil, err
	}
	ciphertext, ok := s.Data["ciphertext"]
	if !ok {
		return nil, errMissingUpdatedKey
	}
	rotatedKey = []byte(ciphertext.(string))
	return rotatedKey, nil
}
<|endoftext|>


<commit_before>package main

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

	"github.com/containerd/containerd/progress"
	"github.com/containerd/containerd/snapshot"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

var snapshotCommand = cli.Command{
	Name:  "snapshot",
	Usage: "snapshot management",
	Flags: snapshotterFlags,
	Subcommands: cli.Commands{
		listSnapshotCommand,
		usageSnapshotCommand,
		removeSnapshotCommand,
		prepareSnapshotCommand,
		treeSnapshotCommand,
		mountSnapshotCommand,
		commitSnapshotCommand,
	},
}

var listSnapshotCommand = cli.Command{
	Name:    "list",
	Aliases: []string{"ls"},
	Usage:   "List snapshots",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
		fmt.Fprintln(tw, "KEY\tPARENT\tKIND\t")

		if err := snapshotter.Walk(ctx, func(ctx context.Context, info snapshot.Info) error {
			fmt.Fprintf(tw, "%v\t%v\t%v\t\n",
				info.Name,
				info.Parent,
				info.Kind)
			return nil
		}); err != nil {
			return err
		}

		return tw.Flush()
	},
}

var usageSnapshotCommand = cli.Command{
	Name:      "usage",
	Usage:     "Usage snapshots",
	ArgsUsage: "[flags] [<key>, ...]",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "b",
			Usage: "display size in bytes",
		},
	},
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		var displaySize func(int64) string
		if clicontext.Bool("b") {
			displaySize = func(s int64) string {
				return fmt.Sprintf("%d", s)
			}
		} else {
			displaySize = func(s int64) string {
				return progress.Bytes(s).String()
			}
		}

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
		fmt.Fprintln(tw, "KEY\tSIZE\tINODES\t")

		if clicontext.NArg() == 0 {
			if err := snapshotter.Walk(ctx, func(ctx context.Context, info snapshot.Info) error {
				usage, err := snapshotter.Usage(ctx, info.Name)
				if err != nil {
					return err
				}
				fmt.Fprintf(tw, "%v\t%s\t%d\t\n", info.Name, displaySize(usage.Size), usage.Inodes)
				return nil
			}); err != nil {
				return err
			}
		} else {
			for _, id := range clicontext.Args() {
				usage, err := snapshotter.Usage(ctx, id)
				if err != nil {
					return err
				}
				fmt.Fprintf(tw, "%v\t%s\t%d\t\n", id, displaySize(usage.Size), usage.Inodes)
			}
		}

		return tw.Flush()
	},
}

var removeSnapshotCommand = cli.Command{
	Name:      "remove",
	Aliases:   []string{"rm"},
	ArgsUsage: "<key> [<key>, ...]",
	Usage:     "remove snapshots",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		for _, key := range clicontext.Args() {
			err = snapshotter.Remove(ctx, key)
			if err != nil {
				return errors.Wrapf(err, "failed to remove %q", key)
			}
		}

		return nil
	},
}

var prepareSnapshotCommand = cli.Command{
	Name:      "prepare",
	Usage:     "prepare a snapshot from a committed snapshot",
	ArgsUsage: "[flags] <key> [<parent>]",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "target, t",
			Usage: "mount target path, will print mount, if provided",
		},
	},
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		if clicontext.NArg() != 2 {
			return cli.ShowSubcommandHelp(clicontext)
		}

		target := clicontext.String("target")
		key := clicontext.Args().Get(0)
		parent := clicontext.Args().Get(1)

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		mounts, err := snapshotter.Prepare(ctx, key, parent)
		if err != nil {
			return err
		}

		if target != "" {
			for _, m := range mounts {
				fmt.Fprintf(os.Stdout, "mount -t %s %s %s -o %s\n", m.Type, m.Source, target, strings.Join(m.Options, ","))
			}
		}

		return nil
	},
}

var mountSnapshotCommand = cli.Command{
	Name:      "mounts",
	Aliases:   []string{"m", "mount"},
	Usage:     "mount gets mount commands for the active snapshots",
	ArgsUsage: "[flags] <target> <key>",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		if clicontext.NArg() != 2 {
			return cli.ShowSubcommandHelp(clicontext)
		}

		target := clicontext.Args().Get(0)
		key := clicontext.Args().Get(1)
		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		mounts, err := snapshotter.Mounts(ctx, key)
		if err != nil {
			return err
		}

		for _, m := range mounts {
			fmt.Fprintf(os.Stdout, "mount -t %s %s %s -o %s\n", m.Type, m.Source, target, strings.Join(m.Options, ","))
		}

		return nil
	},
}

var commitSnapshotCommand = cli.Command{
	Name:      "commit",
	Usage:     "commit an active snapshot into the provided name",
	ArgsUsage: "[flags] <key> <active>",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		if clicontext.NArg() != 2 {
			return cli.ShowSubcommandHelp(clicontext)
		}

		key := clicontext.Args().Get(0)
		active := clicontext.Args().Get(1)

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		return snapshotter.Commit(ctx, key, active)
	},
}

var treeSnapshotCommand = cli.Command{
	Name:  "tree",
	Usage: "Display tree view of snapshot branches",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		tree := make(map[string]*snapshotTreeNode)

		if err := snapshotter.Walk(ctx, func(ctx context.Context, info snapshot.Info) error {
			// Get or create node and add node details
			node := getOrCreateTreeNode(info.Name, tree)
			if info.Parent != "" {
				node.Parent = info.Parent
				p := getOrCreateTreeNode(info.Parent, tree)
				p.Children = append(p.Children, info.Name)
			}

			return nil
		}); err != nil {
			return err
		}

		printTree(tree)

		return nil
	},
}

type snapshotTreeNode struct {
	Name     string
	Parent   string
	Children []string
}

func getOrCreateTreeNode(name string, tree map[string]*snapshotTreeNode) *snapshotTreeNode {
	if node, ok := tree[name]; ok {
		return node
	}
	node := &snapshotTreeNode{
		Name: name,
	}
	tree[name] = node
	return node
}

func printTree(tree map[string]*snapshotTreeNode) {
	for _, node := range tree {
		// Print for root(parent-less) nodes only
		if node.Parent == "" {
			printNode(node.Name, tree, 0)
		}
	}
}

func printNode(name string, tree map[string]*snapshotTreeNode, level int) {
	node := tree[name]
	fmt.Printf("%s\\_ %s\n", strings.Repeat("  ", level), node.Name)
	level++
	for _, child := range node.Children {
		printNode(child, tree, level)
	}
}
<commit_msg>ctr: add `ctr snapshot view`<commit_after>package main

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

	"github.com/containerd/containerd/mount"
	"github.com/containerd/containerd/progress"
	"github.com/containerd/containerd/snapshot"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

var snapshotCommand = cli.Command{
	Name:  "snapshot",
	Usage: "snapshot management",
	Flags: snapshotterFlags,
	Subcommands: cli.Commands{
		listSnapshotCommand,
		usageSnapshotCommand,
		removeSnapshotCommand,
		prepareSnapshotCommand,
		viewSnapshotCommand,
		treeSnapshotCommand,
		mountSnapshotCommand,
		commitSnapshotCommand,
	},
}

var listSnapshotCommand = cli.Command{
	Name:    "list",
	Aliases: []string{"ls"},
	Usage:   "List snapshots",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
		fmt.Fprintln(tw, "KEY\tPARENT\tKIND\t")

		if err := snapshotter.Walk(ctx, func(ctx context.Context, info snapshot.Info) error {
			fmt.Fprintf(tw, "%v\t%v\t%v\t\n",
				info.Name,
				info.Parent,
				info.Kind)
			return nil
		}); err != nil {
			return err
		}

		return tw.Flush()
	},
}

var usageSnapshotCommand = cli.Command{
	Name:      "usage",
	Usage:     "Usage snapshots",
	ArgsUsage: "[flags] [<key>, ...]",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "b",
			Usage: "display size in bytes",
		},
	},
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		var displaySize func(int64) string
		if clicontext.Bool("b") {
			displaySize = func(s int64) string {
				return fmt.Sprintf("%d", s)
			}
		} else {
			displaySize = func(s int64) string {
				return progress.Bytes(s).String()
			}
		}

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
		fmt.Fprintln(tw, "KEY\tSIZE\tINODES\t")

		if clicontext.NArg() == 0 {
			if err := snapshotter.Walk(ctx, func(ctx context.Context, info snapshot.Info) error {
				usage, err := snapshotter.Usage(ctx, info.Name)
				if err != nil {
					return err
				}
				fmt.Fprintf(tw, "%v\t%s\t%d\t\n", info.Name, displaySize(usage.Size), usage.Inodes)
				return nil
			}); err != nil {
				return err
			}
		} else {
			for _, id := range clicontext.Args() {
				usage, err := snapshotter.Usage(ctx, id)
				if err != nil {
					return err
				}
				fmt.Fprintf(tw, "%v\t%s\t%d\t\n", id, displaySize(usage.Size), usage.Inodes)
			}
		}

		return tw.Flush()
	},
}

var removeSnapshotCommand = cli.Command{
	Name:      "remove",
	Aliases:   []string{"rm"},
	ArgsUsage: "<key> [<key>, ...]",
	Usage:     "remove snapshots",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		for _, key := range clicontext.Args() {
			err = snapshotter.Remove(ctx, key)
			if err != nil {
				return errors.Wrapf(err, "failed to remove %q", key)
			}
		}

		return nil
	},
}

var prepareSnapshotCommand = cli.Command{
	Name:      "prepare",
	Usage:     "prepare a snapshot from a committed snapshot",
	ArgsUsage: "[flags] <key> [<parent>]",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "target, t",
			Usage: "mount target path, will print mount, if provided",
		},
	},
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		if clicontext.NArg() != 2 {
			return cli.ShowSubcommandHelp(clicontext)
		}

		target := clicontext.String("target")
		key := clicontext.Args().Get(0)
		parent := clicontext.Args().Get(1)

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		mounts, err := snapshotter.Prepare(ctx, key, parent)
		if err != nil {
			return err
		}

		if target != "" {
			printMounts(target, mounts)
		}

		return nil
	},
}

var viewSnapshotCommand = cli.Command{
	Name:      "view",
	Usage:     "create a read-only snapshot from a committed snapshot",
	ArgsUsage: "[flags] <key> [<parent>]",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "target, t",
			Usage: "mount target path, will print mount, if provided",
		},
	},
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		if clicontext.NArg() != 2 {
			return cli.ShowSubcommandHelp(clicontext)
		}

		target := clicontext.String("target")
		key := clicontext.Args().Get(0)
		parent := clicontext.Args().Get(1)

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		mounts, err := snapshotter.View(ctx, key, parent)
		if err != nil {
			return err
		}

		if target != "" {
			printMounts(target, mounts)
		}

		return nil
	},
}

var mountSnapshotCommand = cli.Command{
	Name:      "mounts",
	Aliases:   []string{"m", "mount"},
	Usage:     "mount gets mount commands for the snapshots",
	ArgsUsage: "[flags] <target> <key>",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		if clicontext.NArg() != 2 {
			return cli.ShowSubcommandHelp(clicontext)
		}

		target := clicontext.Args().Get(0)
		key := clicontext.Args().Get(1)
		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		mounts, err := snapshotter.Mounts(ctx, key)
		if err != nil {
			return err
		}

		printMounts(target, mounts)

		return nil
	},
}

var commitSnapshotCommand = cli.Command{
	Name:      "commit",
	Usage:     "commit an active snapshot into the provided name",
	ArgsUsage: "[flags] <key> <active>",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		if clicontext.NArg() != 2 {
			return cli.ShowSubcommandHelp(clicontext)
		}

		key := clicontext.Args().Get(0)
		active := clicontext.Args().Get(1)

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		return snapshotter.Commit(ctx, key, active)
	},
}

var treeSnapshotCommand = cli.Command{
	Name:  "tree",
	Usage: "Display tree view of snapshot branches",
	Action: func(clicontext *cli.Context) error {
		ctx, cancel := appContext(clicontext)
		defer cancel()

		snapshotter, err := getSnapshotter(clicontext)
		if err != nil {
			return err
		}

		tree := make(map[string]*snapshotTreeNode)

		if err := snapshotter.Walk(ctx, func(ctx context.Context, info snapshot.Info) error {
			// Get or create node and add node details
			node := getOrCreateTreeNode(info.Name, tree)
			if info.Parent != "" {
				node.Parent = info.Parent
				p := getOrCreateTreeNode(info.Parent, tree)
				p.Children = append(p.Children, info.Name)
			}

			return nil
		}); err != nil {
			return err
		}

		printTree(tree)

		return nil
	},
}

type snapshotTreeNode struct {
	Name     string
	Parent   string
	Children []string
}

func getOrCreateTreeNode(name string, tree map[string]*snapshotTreeNode) *snapshotTreeNode {
	if node, ok := tree[name]; ok {
		return node
	}
	node := &snapshotTreeNode{
		Name: name,
	}
	tree[name] = node
	return node
}

func printTree(tree map[string]*snapshotTreeNode) {
	for _, node := range tree {
		// Print for root(parent-less) nodes only
		if node.Parent == "" {
			printNode(node.Name, tree, 0)
		}
	}
}

func printNode(name string, tree map[string]*snapshotTreeNode, level int) {
	node := tree[name]
	fmt.Printf("%s\\_ %s\n", strings.Repeat("  ", level), node.Name)
	level++
	for _, child := range node.Children {
		printNode(child, tree, level)
	}
}

func printMounts(target string, mounts []mount.Mount) {
	// FIXME: This is specific to Unix
	for _, m := range mounts {
		fmt.Printf("mount -t %s %s %s -o %s\n", m.Type, m.Source, target, strings.Join(m.Options, ","))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/spf13/cobra"
)

func main() {
	_ = cobra.Command{}
}
<commit_msg>cmd/fluxctl: first draft, listing services<commit_after>package main

import (
	"fmt"
	"io"
	"net/http"
	"os"

	"github.com/spf13/cobra"
)

// These are the (unfortunately global) flags.
var (
	OptionURL       string
	OptionNamespace string
)

func main() {
	rootCmd := &cobra.Command{
		Use:          "fluxctl",
		Short:        "fluxctl is a commandline client for the fluxd daemon.",
		SilenceUsage: true,
	}
	rootCmd.Flags().StringVarP(&OptionURL, "url", "u", "http://localhost:3030/v0/", "Base URL of the fluxd API server")

	serviceCmd := &cobra.Command{
		Use:   "service <list, ...> [options]",
		Short: "Manipulate platform services.",
	}

	serviceListCmd := &cobra.Command{
		Use:   "list",
		Short: "List services currently running on the platform.",
		RunE:  serviceList,
	}
	serviceListCmd.Flags().StringVarP(&OptionNamespace, "namespace", "n", "default", "Namespace to introspect")

	rootCmd.AddCommand(serviceCmd)
	serviceCmd.AddCommand(serviceListCmd)

	if err := rootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}

func serviceList(cmd *cobra.Command, args []string) error {
	req, err := http.NewRequest("GET", fmt.Sprintf(
		"%s/services?namespace=%s",
		OptionURL,
		OptionNamespace,
	), nil)
	if err != nil {
		return err
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}

	io.Copy(os.Stdout, resp.Body)
	resp.Body.Close()
	return nil
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Google Inc.
//
// 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 main

import (
	"context"
	"fmt"
	"os"
	"regexp"
	"strings"

	"github.com/google/gapid/core/app/auth"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/core/os/android/adb"
	"github.com/google/gapid/gapis/client"
	"github.com/google/gapid/gapis/service"
	"github.com/google/gapid/gapis/service/path"
)

func (f CommandFilterFlags) commandFilter(ctx context.Context, client service.Service, p *path.Capture) (*path.CommandFilter, error) {
	filter := &path.CommandFilter{}
	if f.Context >= 0 {
		contexts, err := client.Get(ctx, p.Contexts().Path())
		if err != nil {
			return nil, log.Err(ctx, err, "Failed to load the contexts")
		}
		filter.Context = contexts.(*service.Contexts).List[f.Context].Id
	}
	return filter, nil
}

func getGapis(ctx context.Context, gapisFlags GapisFlags, gapirFlags GapirFlags) (client.Client, error) {
	args := strings.Fields(gapisFlags.Args)
	if gapirFlags.Args != "" {
		// Pass the arguments for gapir further to gapis. Add flag to tag the
		// gapir argument string for gapis.
		args = append(args, "--gapir-args", gapirFlags.Args)
	}
	if gapisFlags.Profile != "" {
		args = append(args, "-cpuprofile", gapisFlags.Profile)
	}

	var token auth.Token
	if gapisFlags.Port == 0 {
		token = auth.GenToken()
	} else {
		token = auth.Token(gapisFlags.Token)
	}
	client, err := client.Connect(ctx, client.Config{
		Port:  gapisFlags.Port,
		Args:  args,
		Token: token,
	})
	if err != nil {
		return nil, log.Err(ctx, err, "Failed to connect to the GAPIS server")
	}

	// if h := log.GetHandler(ctx); h != nil {
	// 	go client.GetLogStream(ctx, h)
	// }

	return client, nil
}

func getDevice(ctx context.Context, client client.Client, capture *path.Capture, flags GapirFlags) (*path.Device, error) {
	ctx = log.V{"device": flags.Device}.Bind(ctx)
	paths, err := client.GetDevicesForReplay(ctx, capture)
	if err != nil {
		return nil, log.Err(ctx, err, "Failed query list of devices for replay")
	}

	if len(paths) > 0 {
		return paths[0], nil
	}

	log.W(ctx, "No compatible devices found. Attempting to use the first device anyway...")

	paths, err = client.GetDevices(ctx)
	if err != nil {
		return nil, log.Err(ctx, err, "Failed query list of devices")
	}

	if len(paths) > 0 {
		return paths[0], nil
	}

	return nil, log.Err(ctx, nil, "No devices found")
}

func getADBDevice(ctx context.Context, pattern string) (adb.Device, error) {
	devices, err := adb.Devices(ctx)
	if err != nil {
		return nil, err
	}
	if len(devices) == 0 {
		return nil, fmt.Errorf("No devices found")
	}
	log.I(ctx, "Device list:")
	for _, test := range devices {
		log.I(ctx, "  %v", test.Instance().Serial)
	}
	matchingDevices := []adb.Device{}
	if pattern == "" {
		matchingDevices = devices
	} else {
		re := regexp.MustCompile("(?i)" + pattern)
		for _, test := range devices {
			if re.MatchString(test.Instance().Serial) {
				matchingDevices = append(matchingDevices, test)
			}
		}
	}
	if len(matchingDevices) == 0 {
		return nil, fmt.Errorf("No devices matching %q found", pattern)
	} else if len(matchingDevices) > 1 {
		fmt.Fprintln(os.Stderr, "Matching devices:")
		for _, test := range matchingDevices {
			fmt.Fprint(os.Stderr, "    ")
			fmt.Fprintln(os.Stderr, test.Instance().Serial)
		}
		return nil, fmt.Errorf("Multiple devices matching %q found", pattern)
	}
	return matchingDevices[0], nil
}

func getEvents(ctx context.Context, client service.Service, p *path.Events) ([]*service.Event, error) {
	b, err := client.Get(ctx, p.Path())
	if err != nil {
		return nil, log.Errf(ctx, err, "Couldn't get events at: %v", p.Text())
	}
	return b.(*service.Events).List, nil
}

func getCommand(ctx context.Context, client service.Service, p *path.Command) (*service.Command, error) {
	boxedCmd, err := client.Get(ctx, p.Path())
	if err != nil {
		return nil, log.Errf(ctx, err, "Couldn't load command at: %v", p.Text())
	}
	return boxedCmd.(*service.Command), nil
}

func getConstantSet(ctx context.Context, client service.Service, p *path.ConstantSet) (*service.ConstantSet, error) {
	boxedConstants, err := client.Get(ctx, p.Path())
	if err != nil {
		return nil, log.Errf(ctx, err, "Couldn't local constant set at: %v", p.Text())
	}
	return boxedConstants.(*service.ConstantSet), nil
}

func printCommand(ctx context.Context, client service.Service, p *path.Command, c *service.Command) error {
	indices := make([]string, len(p.Index))
	for i, v := range p.Index {
		indices[i] = fmt.Sprintf("%d", v)
	}

	params := make([]string, len(c.Parameters))
	for i, p := range c.Parameters {
		v := p.Value.Get()
		if p.Constants != nil {
			constants, err := getConstantSet(ctx, client, p.Constants)
			if err != nil {
				return log.Err(ctx, err, "Couldn't fetch constant set")
			}
			v = constants.Sprint(v)
		}
		params[i] = fmt.Sprintf("%v: %v", p.Name, v)
	}
	fmt.Fprintf(os.Stdout, "%v %v(%v)", indices, c.Name, strings.Join(params, ", "))
	if c.Result != nil {
		v := c.Result.Value.Get()
		if c.Result.Constants != nil {
			constants, err := getConstantSet(ctx, client, c.Result.Constants)
			if err != nil {
				return log.Err(ctx, err, "Couldn't fetch constant set")
			}
			v = constants.Sprint(v)
		}
		fmt.Fprintf(os.Stdout, " → %v", v)
	}
	fmt.Fprintln(os.Stdout, "")
	return nil
}

func getAndPrintCommand(ctx context.Context, client service.Service, p *path.Command) error {
	cmd, err := getCommand(ctx, client, p)
	if err != nil {
		return err
	}
	return printCommand(ctx, client, p, cmd)
}
<commit_msg>gapit: Uncomment the GetLogStream go routine.<commit_after>// Copyright (C) 2017 Google Inc.
//
// 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 main

import (
	"context"
	"fmt"
	"os"
	"regexp"
	"strings"

	"github.com/google/gapid/core/app/auth"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/core/os/android/adb"
	"github.com/google/gapid/gapis/client"
	"github.com/google/gapid/gapis/service"
	"github.com/google/gapid/gapis/service/path"
)

func (f CommandFilterFlags) commandFilter(ctx context.Context, client service.Service, p *path.Capture) (*path.CommandFilter, error) {
	filter := &path.CommandFilter{}
	if f.Context >= 0 {
		contexts, err := client.Get(ctx, p.Contexts().Path())
		if err != nil {
			return nil, log.Err(ctx, err, "Failed to load the contexts")
		}
		filter.Context = contexts.(*service.Contexts).List[f.Context].Id
	}
	return filter, nil
}

func getGapis(ctx context.Context, gapisFlags GapisFlags, gapirFlags GapirFlags) (client.Client, error) {
	args := strings.Fields(gapisFlags.Args)
	if gapirFlags.Args != "" {
		// Pass the arguments for gapir further to gapis. Add flag to tag the
		// gapir argument string for gapis.
		args = append(args, "--gapir-args", gapirFlags.Args)
	}
	if gapisFlags.Profile != "" {
		args = append(args, "-cpuprofile", gapisFlags.Profile)
	}

	var token auth.Token
	if gapisFlags.Port == 0 {
		token = auth.GenToken()
	} else {
		token = auth.Token(gapisFlags.Token)
	}
	client, err := client.Connect(ctx, client.Config{
		Port:  gapisFlags.Port,
		Args:  args,
		Token: token,
	})
	if err != nil {
		return nil, log.Err(ctx, err, "Failed to connect to the GAPIS server")
	}

	if h := log.GetHandler(ctx); h != nil {
		go client.GetLogStream(ctx, h)
	}

	return client, nil
}

func getDevice(ctx context.Context, client client.Client, capture *path.Capture, flags GapirFlags) (*path.Device, error) {
	ctx = log.V{"device": flags.Device}.Bind(ctx)
	paths, err := client.GetDevicesForReplay(ctx, capture)
	if err != nil {
		return nil, log.Err(ctx, err, "Failed query list of devices for replay")
	}

	if len(paths) > 0 {
		return paths[0], nil
	}

	log.W(ctx, "No compatible devices found. Attempting to use the first device anyway...")

	paths, err = client.GetDevices(ctx)
	if err != nil {
		return nil, log.Err(ctx, err, "Failed query list of devices")
	}

	if len(paths) > 0 {
		return paths[0], nil
	}

	return nil, log.Err(ctx, nil, "No devices found")
}

func getADBDevice(ctx context.Context, pattern string) (adb.Device, error) {
	devices, err := adb.Devices(ctx)
	if err != nil {
		return nil, err
	}
	if len(devices) == 0 {
		return nil, fmt.Errorf("No devices found")
	}
	log.I(ctx, "Device list:")
	for _, test := range devices {
		log.I(ctx, "  %v", test.Instance().Serial)
	}
	matchingDevices := []adb.Device{}
	if pattern == "" {
		matchingDevices = devices
	} else {
		re := regexp.MustCompile("(?i)" + pattern)
		for _, test := range devices {
			if re.MatchString(test.Instance().Serial) {
				matchingDevices = append(matchingDevices, test)
			}
		}
	}
	if len(matchingDevices) == 0 {
		return nil, fmt.Errorf("No devices matching %q found", pattern)
	} else if len(matchingDevices) > 1 {
		fmt.Fprintln(os.Stderr, "Matching devices:")
		for _, test := range matchingDevices {
			fmt.Fprint(os.Stderr, "    ")
			fmt.Fprintln(os.Stderr, test.Instance().Serial)
		}
		return nil, fmt.Errorf("Multiple devices matching %q found", pattern)
	}
	return matchingDevices[0], nil
}

func getEvents(ctx context.Context, client service.Service, p *path.Events) ([]*service.Event, error) {
	b, err := client.Get(ctx, p.Path())
	if err != nil {
		return nil, log.Errf(ctx, err, "Couldn't get events at: %v", p.Text())
	}
	return b.(*service.Events).List, nil
}

func getCommand(ctx context.Context, client service.Service, p *path.Command) (*service.Command, error) {
	boxedCmd, err := client.Get(ctx, p.Path())
	if err != nil {
		return nil, log.Errf(ctx, err, "Couldn't load command at: %v", p.Text())
	}
	return boxedCmd.(*service.Command), nil
}

func getConstantSet(ctx context.Context, client service.Service, p *path.ConstantSet) (*service.ConstantSet, error) {
	boxedConstants, err := client.Get(ctx, p.Path())
	if err != nil {
		return nil, log.Errf(ctx, err, "Couldn't local constant set at: %v", p.Text())
	}
	return boxedConstants.(*service.ConstantSet), nil
}

func printCommand(ctx context.Context, client service.Service, p *path.Command, c *service.Command) error {
	indices := make([]string, len(p.Index))
	for i, v := range p.Index {
		indices[i] = fmt.Sprintf("%d", v)
	}

	params := make([]string, len(c.Parameters))
	for i, p := range c.Parameters {
		v := p.Value.Get()
		if p.Constants != nil {
			constants, err := getConstantSet(ctx, client, p.Constants)
			if err != nil {
				return log.Err(ctx, err, "Couldn't fetch constant set")
			}
			v = constants.Sprint(v)
		}
		params[i] = fmt.Sprintf("%v: %v", p.Name, v)
	}
	fmt.Fprintf(os.Stdout, "%v %v(%v)", indices, c.Name, strings.Join(params, ", "))
	if c.Result != nil {
		v := c.Result.Value.Get()
		if c.Result.Constants != nil {
			constants, err := getConstantSet(ctx, client, c.Result.Constants)
			if err != nil {
				return log.Err(ctx, err, "Couldn't fetch constant set")
			}
			v = constants.Sprint(v)
		}
		fmt.Fprintf(os.Stdout, " → %v", v)
	}
	fmt.Fprintln(os.Stdout, "")
	return nil
}

func getAndPrintCommand(ctx context.Context, client service.Service, p *path.Command) error {
	cmd, err := getCommand(ctx, client, p)
	if err != nil {
		return err
	}
	return printCommand(ctx, client, p, cmd)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"io"
	"net/http"
	"os"

	"github.com/gorilla/mux"

	"github.com/skygeario/skygear-server/pkg/core/auth"
	coreConfig "github.com/skygeario/skygear-server/pkg/core/config"
	"github.com/skygeario/skygear-server/pkg/core/db"
	"github.com/skygeario/skygear-server/pkg/core/logging"
	coreMiddleware "github.com/skygeario/skygear-server/pkg/core/middleware"
	"github.com/skygeario/skygear-server/pkg/core/redis"
	"github.com/skygeario/skygear-server/pkg/core/server"
	"github.com/skygeario/skygear-server/pkg/gateway"
	gatewayConfig "github.com/skygeario/skygear-server/pkg/gateway/config"
	"github.com/skygeario/skygear-server/pkg/gateway/handler"
	"github.com/skygeario/skygear-server/pkg/gateway/middleware"
	"github.com/skygeario/skygear-server/pkg/gateway/provider"
	"github.com/skygeario/skygear-server/pkg/gateway/store"
	pqStore "github.com/skygeario/skygear-server/pkg/gateway/store/pq"
	standaloneStore "github.com/skygeario/skygear-server/pkg/gateway/store/standalone"
)

var config gatewayConfig.Configuration

func init() {
	// logging initialization
	logging.SetModule("gateway")

	logger := logging.LoggerEntry("gateway")
	if err := config.ReadFromEnv(); err != nil {
		logger.WithError(err).Panic(
			"Fail to load config for starting gateway server")
	}

	logger.WithField("config", config).Debug("Gateway config")
}

func main() {
	logger := logging.LoggerEntry("gateway")

	// create gateway store
	var store store.GatewayStore
	var connErr error
	if config.Standalone {
		filename := config.StandaloneTenantConfigurationFile
		reader, err := os.Open(filename)
		if err != nil {
			logger.WithError(err).Panic("Fail to open config file")
		}
		tenantConfig, err := coreConfig.NewTenantConfigurationFromYAML(reader)
		if err != nil {
			logger.WithError(err).Panic("Fail to load config from YAML")
		}
		store = &standaloneStore.Store{
			TenantConfig: *tenantConfig,
		}
	} else {
		store, connErr = pqStore.NewGatewayStore(
			context.Background(),
			config.ConnectionStr,
			logger,
		)
		if connErr != nil {
			logger.WithError(connErr).Panic("Fail to create db conn")
		}
	}
	defer store.Close()

	gatewayDependency := gateway.DependencyMap{
		UseInsecureCookie: config.UseInsecureCookie,
	}
	dbPool := db.NewPool()
	redisPool := redis.NewPool(config.Redis)

	rr := mux.NewRouter()
	rr.HandleFunc("/_healthz", HealthCheckHandler)

	r := rr.PathPrefix("/").Subrouter()
	// RecoverMiddleware must come first
	r.Use(coreMiddleware.RecoverMiddleware{
		RecoverHandler: server.DefaultRecoverPanicHandler,
	}.Handle)

	r.Use(coreMiddleware.RequestIDMiddleware{}.Handle)
	r.Use(middleware.FindAppMiddleware{Store: store}.Handle)

	gr := r.PathPrefix("/_{gear}").Subrouter()

	gr.Use(coreMiddleware.TenantConfigurationMiddleware{
		ConfigurationProvider: provider.GatewayTenantConfigurationProvider{
			Store: store,
		},
	}.Handle)
	gr.Use(middleware.TenantAuthzMiddleware{
		Store:         store,
		Configuration: config,
	}.Handle)
	gr.Use(coreMiddleware.CORSMiddleware{}.Handle)

	gr.HandleFunc("/{rest:.*}", handler.NewGearHandler("rest"))

	cr := r.PathPrefix("/").Subrouter()

	cr.Use(coreMiddleware.TenantConfigurationMiddleware{
		ConfigurationProvider: provider.GatewayTenantConfigurationProvider{
			Store: store,
		},
	}.Handle)

	cr.Use(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			r = db.InitRequestDBContext(r, dbPool)
			r = auth.InitRequestAuthContext(r)
			r = r.WithContext(redis.WithRedis(r.Context(), redisPool))
			next.ServeHTTP(w, r)
		})
	})

	cr.Use(middleware.FindDeploymentRouteMiddleware{
		RestPathIdentifier: "rest",
		Store:              store,
	}.Handle)

	cr.Use(coreMiddleware.Injecter{
		MiddlewareFactory: coreMiddleware.AuthnMiddlewareFactory{},
		Dependency:        gatewayDependency,
	}.Handle)

	cr.Use(coreMiddleware.Injecter{
		MiddlewareFactory: middleware.AuthInfoMiddlewareFactory{},
		Dependency:        gatewayDependency,
	}.Handle)

	cr.Use(coreMiddleware.CORSMiddleware{}.Handle)

	cr.HandleFunc("/{rest:.*}", handler.NewDeploymentRouteHandler())

	srv := &http.Server{
		Addr:    config.Host,
		Handler: rr, // Pass our instance of gorilla/mux in.
	}

	logger.Info("Start gateway server")
	if err := srv.ListenAndServe(); err != nil {
		logger.Errorf("Fail to start gateway server %v", err)
	}
}

// HealthCheckHandler is basic handler for server health check
func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")
	io.WriteString(w, "OK")
}
<commit_msg>Setup timeout at gateway<commit_after>package main

import (
	"context"
	"io"
	"net/http"
	"os"
	"time"

	"github.com/gorilla/mux"

	"github.com/skygeario/skygear-server/pkg/core/auth"
	coreConfig "github.com/skygeario/skygear-server/pkg/core/config"
	"github.com/skygeario/skygear-server/pkg/core/db"
	"github.com/skygeario/skygear-server/pkg/core/logging"
	coreMiddleware "github.com/skygeario/skygear-server/pkg/core/middleware"
	"github.com/skygeario/skygear-server/pkg/core/redis"
	"github.com/skygeario/skygear-server/pkg/core/server"
	"github.com/skygeario/skygear-server/pkg/gateway"
	gatewayConfig "github.com/skygeario/skygear-server/pkg/gateway/config"
	"github.com/skygeario/skygear-server/pkg/gateway/handler"
	"github.com/skygeario/skygear-server/pkg/gateway/middleware"
	"github.com/skygeario/skygear-server/pkg/gateway/provider"
	"github.com/skygeario/skygear-server/pkg/gateway/store"
	pqStore "github.com/skygeario/skygear-server/pkg/gateway/store/pq"
	standaloneStore "github.com/skygeario/skygear-server/pkg/gateway/store/standalone"
)

var config gatewayConfig.Configuration

func init() {
	// logging initialization
	logging.SetModule("gateway")

	logger := logging.LoggerEntry("gateway")
	if err := config.ReadFromEnv(); err != nil {
		logger.WithError(err).Panic(
			"Fail to load config for starting gateway server")
	}

	logger.WithField("config", config).Debug("Gateway config")
}

func main() {
	logger := logging.LoggerEntry("gateway")

	// create gateway store
	var store store.GatewayStore
	var connErr error
	if config.Standalone {
		filename := config.StandaloneTenantConfigurationFile
		reader, err := os.Open(filename)
		if err != nil {
			logger.WithError(err).Panic("Fail to open config file")
		}
		tenantConfig, err := coreConfig.NewTenantConfigurationFromYAML(reader)
		if err != nil {
			logger.WithError(err).Panic("Fail to load config from YAML")
		}
		store = &standaloneStore.Store{
			TenantConfig: *tenantConfig,
		}
	} else {
		store, connErr = pqStore.NewGatewayStore(
			context.Background(),
			config.ConnectionStr,
			logger,
		)
		if connErr != nil {
			logger.WithError(connErr).Panic("Fail to create db conn")
		}
	}
	defer store.Close()

	gatewayDependency := gateway.DependencyMap{
		UseInsecureCookie: config.UseInsecureCookie,
	}
	dbPool := db.NewPool()
	redisPool := redis.NewPool(config.Redis)

	rr := mux.NewRouter()
	rr.HandleFunc("/_healthz", HealthCheckHandler)

	r := rr.PathPrefix("/").Subrouter()
	// RecoverMiddleware must come first
	r.Use(coreMiddleware.RecoverMiddleware{
		RecoverHandler: server.DefaultRecoverPanicHandler,
	}.Handle)

	r.Use(coreMiddleware.RequestIDMiddleware{}.Handle)
	r.Use(middleware.FindAppMiddleware{Store: store}.Handle)

	gr := r.PathPrefix("/_{gear}").Subrouter()

	gr.Use(coreMiddleware.TenantConfigurationMiddleware{
		ConfigurationProvider: provider.GatewayTenantConfigurationProvider{
			Store: store,
		},
	}.Handle)
	gr.Use(middleware.TenantAuthzMiddleware{
		Store:         store,
		Configuration: config,
	}.Handle)
	gr.Use(coreMiddleware.CORSMiddleware{}.Handle)

	gr.HandleFunc("/{rest:.*}", handler.NewGearHandler("rest"))

	cr := r.PathPrefix("/").Subrouter()

	cr.Use(coreMiddleware.TenantConfigurationMiddleware{
		ConfigurationProvider: provider.GatewayTenantConfigurationProvider{
			Store: store,
		},
	}.Handle)

	cr.Use(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			r = db.InitRequestDBContext(r, dbPool)
			r = auth.InitRequestAuthContext(r)
			r = r.WithContext(redis.WithRedis(r.Context(), redisPool))
			next.ServeHTTP(w, r)
		})
	})

	cr.Use(middleware.FindDeploymentRouteMiddleware{
		RestPathIdentifier: "rest",
		Store:              store,
	}.Handle)

	cr.Use(coreMiddleware.Injecter{
		MiddlewareFactory: coreMiddleware.AuthnMiddlewareFactory{},
		Dependency:        gatewayDependency,
	}.Handle)

	cr.Use(coreMiddleware.Injecter{
		MiddlewareFactory: middleware.AuthInfoMiddlewareFactory{},
		Dependency:        gatewayDependency,
	}.Handle)

	cr.Use(coreMiddleware.CORSMiddleware{}.Handle)

	cr.HandleFunc("/{rest:.*}", handler.NewDeploymentRouteHandler())

	srv := &http.Server{
		Addr:         config.Host,
		ReadTimeout:  time.Second * 60,
		WriteTimeout: time.Second * 60,
		IdleTimeout:  time.Second * 60,
		Handler:      rr, // Pass our instance of gorilla/mux in.
	}

	logger.Info("Start gateway server")
	if err := srv.ListenAndServe(); err != nil {
		logger.Errorf("Fail to start gateway server %v", err)
	}
}

// HealthCheckHandler is basic handler for server health check
func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")
	io.WriteString(w, "OK")
}
<|endoftext|>


<commit_before>// Hap - the simple and effective provisioner
// Copyright (c) 2015 Garrett Woodworth (https://github.com/gwoo)
// The BSD License http://opensource.org/licenses/bsd-license.php.

package cli

import (
	"flag"
	"fmt"
	"strings"

	"github.com/gwoo/hap"
)

// Add the exec command
func init() {
	Commands.Add("exec", &ExecCmd{})
}

// Exec command
type ExecCmd struct{}

// Does this command expect a remote
func (cmd *ExecCmd) IsRemote() bool {
	return true
}

// Get help on the exec command
func (cmd *ExecCmd) Help() string {
	return "hap exec <script>\tExecute a script on the remote host."
}

// Execute a script from the repo on the remote host
func (cmd *ExecCmd) Run(remote *hap.Remote) (string, error) {
	args := flag.Args()
	if len(args) <= 1 {
		return "", fmt.Errorf("error: expects <script>")
	}
	if result, err := Commands.Get("push").Run(remote); err != nil {
		return result, err
	}
	ex := strings.Join(args[1:], " ")
	if err := remote.Execute([]string{"cd " + remote.Dir, "./" + ex}); err != nil {
		result := fmt.Sprintf("[%s] `%s` failed.", remote.Host.Name, args[1])
		return result, err
	}
	result := fmt.Sprintf("[%s] `%s` completed.", remote.Host.Name, args[1])
	return result, nil
}
<commit_msg>Fix warnings from go lint in cmd/hap/cli/exec.go<commit_after>// Hap - the simple and effective provisioner
// Copyright (c) 2015 Garrett Woodworth (https://github.com/gwoo)
// The BSD License http://opensource.org/licenses/bsd-license.php.

package cli

import (
	"flag"
	"fmt"
	"strings"

	"github.com/gwoo/hap"
)

// Add the exec command
func init() {
	Commands.Add("exec", &ExecCmd{})
}

// ExecCmd is the command
type ExecCmd struct{}

// IsRemote returns whether the command expects a remote or not
func (cmd *ExecCmd) IsRemote() bool {
	return true
}

// Help returns help on hap exec <script>
func (cmd *ExecCmd) Help() string {
	return "hap exec <script>\tExecute a script on the remote host."
}

// Run takes a remote and executes a script from the repo on it
func (cmd *ExecCmd) Run(remote *hap.Remote) (string, error) {
	args := flag.Args()
	if len(args) <= 1 {
		return "", fmt.Errorf("error: expects <script>")
	}
	if result, err := Commands.Get("push").Run(remote); err != nil {
		return result, err
	}
	ex := strings.Join(args[1:], " ")
	if err := remote.Execute([]string{"cd " + remote.Dir, "./" + ex}); err != nil {
		result := fmt.Sprintf("[%s] `%s` failed.", remote.Host.Name, args[1])
		return result, err
	}
	result := fmt.Sprintf("[%s] `%s` completed.", remote.Host.Name, args[1])
	return result, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"

	"github.com/kopia/kopia/fs"

	"github.com/kopia/kopia/repo"
	"github.com/kopia/kopia/vault"
)

// ParseObjectID interprets the given ID string and returns corresponding repo.ObjectID.
// The string can be:
// - backupID (vxxxxxx/12312312)
// -
func ParseObjectID(id string, vlt vault.Reader) (repo.ObjectID, error) {
	head, tail := splitHeadTail(id)
	if len(head) == 0 {
		return "", fmt.Errorf("invalid object ID: %v", id)
	}

	oid, err := vlt.ResolveObjectID(head)
	if err != nil {
		return "", err
	}

	if tail == "" {
		return oid, nil
	}

	r, err := vlt.OpenRepository()
	if err != nil {
		return "", fmt.Errorf("cannot open repository: %v", err)
	}

	return parseNestedObjectID(oid, tail, r)
}

func parseNestedObjectID(current repo.ObjectID, id string, r repo.Repository) (repo.ObjectID, error) {
	head, tail := splitHeadTail(id)
	for head != "" {
		d, err := r.Open(current)
		if err != nil {
			return "", err
		}

		dir, err := fs.ReadDirectory(d, "")
		if err != nil {
			return "", fmt.Errorf("entry not found '%v': parent is not a directory.", head)
		}

		e := dir.FindByName(head)
		if e == nil {
			return "", fmt.Errorf("entry not found: '%v'", head)
		}

		current = e.ObjectID

		head, tail = splitHeadTail(tail)
	}

	return current, nil
}

func splitHeadTail(id string) (string, string) {
	p := strings.Index(id, "/")
	if p < 0 {
		return id, ""
	}

	return id[:p], id[p+1:]
}
<commit_msg>cleanup<commit_after>package main

import (
	"fmt"
	"strings"

	"github.com/kopia/kopia/fs"

	"github.com/kopia/kopia/repo"
	"github.com/kopia/kopia/vault"
)

// ParseObjectID interprets the given ID string and returns corresponding repo.ObjectID.
// The string can be:
// - backupID (vxxxxxx/12312312)
// -
func ParseObjectID(id string, vlt vault.Reader) (repo.ObjectID, error) {
	head, tail := splitHeadTail(id)
	if len(head) == 0 {
		return "", fmt.Errorf("invalid object ID: %v", id)
	}

	oid, err := vlt.ResolveObjectID(head)
	if err != nil {
		return "", err
	}

	if tail == "" {
		return oid, nil
	}

	r, err := vlt.OpenRepository()
	if err != nil {
		return "", fmt.Errorf("cannot open repository: %v", err)
	}

	return parseNestedObjectID(oid, tail, r)
}

func parseNestedObjectID(current repo.ObjectID, id string, r repo.Repository) (repo.ObjectID, error) {
	head, tail := splitHeadTail(id)
	for head != "" {
		d, err := r.Open(current)
		if err != nil {
			return "", err
		}

		dir, err := fs.ReadDirectory(d, "")
		if err != nil {
			return "", fmt.Errorf("entry not found '%v': parent is not a directory", head)
		}

		e := dir.FindByName(head)
		if e == nil {
			return "", fmt.Errorf("entry not found: '%v'", head)
		}

		current = e.ObjectID

		head, tail = splitHeadTail(tail)
	}

	return current, nil
}

func splitHeadTail(id string) (string, string) {
	p := strings.Index(id, "/")
	if p < 0 {
		return id, ""
	}

	return id[:p], id[p+1:]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/fsnotify/fsnotify"
)

type RecursiveWatcher struct {
	watcher   *fsnotify.Watcher
	paths     map[string]bool
	recursive bool
}

func NewRecursiveWatcher(recursive bool) (*RecursiveWatcher, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, err
	}
	return &RecursiveWatcher{watcher, make(map[string]bool), recursive}, nil
}

func (rw *RecursiveWatcher) Close() error {
	return rw.watcher.Close()
}

func (rw *RecursiveWatcher) AddPath(root string) error {
	info, err := os.Stat(root)
	if err != nil {
		return err
	}

	if info.Mode().IsRegular() {
		root = filepath.Dir(root)
		if rw.paths[root] {
			return nil
		}
		if err := rw.watcher.Add(root); err != nil {
			return err
		}
		rw.paths[root] = true
		return nil
	} else if !rw.recursive {
		if rw.paths[root] {
			return nil
		}
		if err := rw.watcher.Add(root); err != nil {
			return err
		}
		rw.paths[root] = true
		return nil
	} else {
		return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if info.Mode().IsDir() {
				if !validDir(info) || rw.paths[path] {
					return filepath.SkipDir
				}
				if err := rw.watcher.Add(path); err != nil {
					return err
				}
				rw.paths[path] = true
			}
			return nil
		})
	}
}

func (rw *RecursiveWatcher) Run() chan string {
	files := make(chan string, 10)
	go func() {
		for rw.watcher.Events != nil && rw.watcher.Errors != nil {
			select {
			case event, ok := <-rw.watcher.Events:
				fmt.Println(event)
				if !ok {
					rw.watcher.Events = nil
					break
				}
				if info, err := os.Stat(event.Name); err == nil {
					if validDir(info) {
						if event.Op&fsnotify.Create == fsnotify.Create {
							if err := rw.AddPath(event.Name); err != nil {
								Error.Println(err)
							}
						}
					} else if validFile(info) {
						if event.Op&fsnotify.Write == fsnotify.Write {
							files <- event.Name
						}
					}
				}
			case err, ok := <-rw.watcher.Errors:
				if !ok {
					rw.watcher.Errors = nil
					break
				}
				Error.Println(err)
			}
		}
		close(files)
	}()
	return files
}
<commit_msg>Remove printf<commit_after>package main

import (
	"os"
	"path/filepath"

	"github.com/fsnotify/fsnotify"
)

type RecursiveWatcher struct {
	watcher   *fsnotify.Watcher
	paths     map[string]bool
	recursive bool
}

func NewRecursiveWatcher(recursive bool) (*RecursiveWatcher, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, err
	}
	return &RecursiveWatcher{watcher, make(map[string]bool), recursive}, nil
}

func (rw *RecursiveWatcher) Close() error {
	return rw.watcher.Close()
}

func (rw *RecursiveWatcher) AddPath(root string) error {
	info, err := os.Stat(root)
	if err != nil {
		return err
	}

	if info.Mode().IsRegular() {
		root = filepath.Dir(root)
		if rw.paths[root] {
			return nil
		}
		if err := rw.watcher.Add(root); err != nil {
			return err
		}
		rw.paths[root] = true
		return nil
	} else if !rw.recursive {
		if rw.paths[root] {
			return nil
		}
		if err := rw.watcher.Add(root); err != nil {
			return err
		}
		rw.paths[root] = true
		return nil
	} else {
		return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if info.Mode().IsDir() {
				if !validDir(info) || rw.paths[path] {
					return filepath.SkipDir
				}
				if err := rw.watcher.Add(path); err != nil {
					return err
				}
				rw.paths[path] = true
			}
			return nil
		})
	}
}

func (rw *RecursiveWatcher) Run() chan string {
	files := make(chan string, 10)
	go func() {
		for rw.watcher.Events != nil && rw.watcher.Errors != nil {
			select {
			case event, ok := <-rw.watcher.Events:
				if !ok {
					rw.watcher.Events = nil
					break
				}
				if info, err := os.Stat(event.Name); err == nil {
					if validDir(info) {
						if event.Op&fsnotify.Create == fsnotify.Create {
							if err := rw.AddPath(event.Name); err != nil {
								Error.Println(err)
							}
						}
					} else if validFile(info) {
						if event.Op&fsnotify.Write == fsnotify.Write {
							files <- event.Name
						}
					}
				}
			case err, ok := <-rw.watcher.Errors:
				if !ok {
					rw.watcher.Errors = nil
					break
				}
				Error.Println(err)
			}
		}
		close(files)
	}()
	return files
}
<|endoftext|>


<commit_before>// Copyright 2016 Marc-Antoine Ruel. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// playing is a small app to play with the pins, nothing more. You are not
// expected to use it as-is.
package main

import (
	"fmt"
	"os"
	"reflect"

	"github.com/maruel/dlibox-go/anim1d"
	"github.com/maruel/dlibox-go/apa102"
)

func printFrame(p anim1d.Pattern, l int) {
	// Generate a frame.
	pixels := make(anim1d.Frame, l)
	p.NextFrame(pixels, 0)

	// Convert to apa102 protocol.
	var d []byte
	apa102.Raster(pixels, &d)

	// Print it.
	const cols = 16
	fmt.Printf("uint8_t %s[] = {", reflect.TypeOf(p).Elem().Name())
	for i, b := range d {
		if i%cols == 0 {
			fmt.Printf("\n  ")
		}
		fmt.Printf("0x%02x,", b)
		if i%cols != cols-1 && i != len(d)-1 {
			fmt.Printf(" ")
		}
	}
	fmt.Printf("\n};\n")
}

func mainImpl() error {
	printFrame(&anim1d.Rainbow{}, 144)
	printFrame(&anim1d.Color{0x7f, 0x7f, 0x7f}, 144)
	return nil
}

func main() {
	if err := mainImpl(); err != nil {
		fmt.Fprintf(os.Stderr, "playing\n: %s.\n", err)
		os.Exit(1)
	}
}
<commit_msg>Print colors instead of APA102 protocol.<commit_after>// Copyright 2016 Marc-Antoine Ruel. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// playing is a small app to play with the pins, nothing more. You are not
// expected to use it as-is.
package main

import (
	"fmt"
	"os"
	"reflect"

	"github.com/maruel/dlibox-go/anim1d"
	"github.com/maruel/dlibox-go/apa102"
)

func printFrameRaw(p anim1d.Pattern, l int) {
	// Generate a frame.
	pixels := make(anim1d.Frame, l)
	p.NextFrame(pixels, 0)

	// Convert to apa102 protocol.
	var d []byte
	apa102.Raster(pixels, &d)

	// Print it.
	const cols = 16
	fmt.Printf("const uint8_t %s[] = {", reflect.TypeOf(p).Elem().Name())
	for i, b := range d {
		if i%cols == 0 {
			fmt.Printf("\n  ")
		}
		fmt.Printf("0x%02x,", b)
		if i%cols != cols-1 && i != len(d)-1 {
			fmt.Printf(" ")
		}
	}
	fmt.Printf("\n};\n")
}

func printFrame(p anim1d.Pattern, l int) {
	// Generate a frame.
	pixels := make(anim1d.Frame, l)
	p.NextFrame(pixels, 0)

	// Print it.
	const cols = 16 / 3
	name := reflect.TypeOf(p).Elem().Name()
	fmt.Printf("const uint8_t %s_[] = {", name)
	for i, b := range pixels {
		if i%cols == 0 {
			fmt.Printf("\n  ")
		}
		fmt.Printf("0x%02x, 0x%02x, 0x%02x,", b.R, b.G, b.B)
		if i%cols != cols-1 && i != len(pixels)-1 {
			fmt.Printf(" ")
		}
	}
	fmt.Printf("\n};\n\nconst Color *const %s = reinterpret_cast<const Color *>(%s_);\n\n", name, name)
}

func mainImpl() error {
	printFrame(&anim1d.Rainbow{}, 144)
	printFrame(&anim1d.Color{0x7f, 0x7f, 0x7f}, 144)
	return nil
}

func main() {
	if err := mainImpl(); err != nil {
		fmt.Fprintf(os.Stderr, "playing\n: %s.\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>/*
rqlite -- a replicated SQLite database.

rqlite is a distributed system that provides a replicated SQLite database.
rqlite is written in Go and uses Raft to achieve consensus across all the
instances of the SQLite databases. rqlite ensures that every change made to
the database is made to a majority of underlying SQLite files, or none-at-all.
*/

package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"runtime/pprof"
	"strings"

	sql "github.com/otoolep/rqlite/db"
	httpd "github.com/otoolep/rqlite/http"
	"github.com/otoolep/rqlite/store"
)

const sqliteDSN = "db.sqlite"

// These variables are populated via the Go linker.
var (
	version = "2"
	commit  string
	branch  string
)

var httpAddr string
var authFile string
var x509Cert string
var x509Key string
var raftAddr string
var joinAddr string
var noVerify bool
var expvar bool
var dsn string
var inMem bool
var disRedirect bool
var showVersion bool
var cpuprofile string

const desc = `rqlite is a distributed system that provides a replicated SQLite database.`

func init() {
	flag.StringVar(&httpAddr, "http", "localhost:4001", "HTTP query server address. Set X.509 cert and key for HTTPS.")
	flag.StringVar(&x509Cert, "x509cert", "", "Path to X.509 certificate")
	flag.StringVar(&x509Key, "x509key", "", "Path to X.509 private key for certificate")
	flag.StringVar(&authFile, "auth", "", "Path to authentication and authorization file. If not set, not enabled.")
	flag.StringVar(&raftAddr, "raft", "localhost:4002", "Raft communication bind address")
	flag.StringVar(&joinAddr, "join", "", "protocol://host:port of leader to join")
	flag.BoolVar(&noVerify, "noverify", false, "Skip verification of any HTTPS cert when joining")
	flag.BoolVar(&expvar, "expvar", true, "Serve expvar data on HTTP server")
	flag.StringVar(&dsn, "dsn", "", `SQLite DSN parameters. E.g. "cache=shared&mode=memory"`)
	flag.BoolVar(&inMem, "mem", false, "Use an in-memory database")
	flag.BoolVar(&disRedirect, "noredir", true, "Disable leader-redirect")
	flag.BoolVar(&showVersion, "version", false, "Show version information and exit")
	flag.StringVar(&cpuprofile, "cpuprofile", "", "Write CPU profile to file")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "\n%s\n\n", desc)
		fmt.Fprintf(os.Stderr, "Usage: %s [arguments] <data directory>\n", os.Args[0])
		flag.PrintDefaults()
	}

	// If commit, branch, or build time are not set, make that clear.
	if commit == "" {
		commit = "unknown"
	}
	if branch == "" {
		branch = "unknown"
	}
}

func main() {
	flag.Parse()

	if showVersion {
		fmt.Printf("rqlited version %s (commit %s)\n", version, commit)
		os.Exit(0)
	}

	// Ensure the data path is set.
	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	dataPath := flag.Arg(0)

	// Configure logging and pump out initial message.
	log.SetFlags(log.LstdFlags)
	log.SetPrefix("[rqlited] ")
	log.Printf("rqlited starting, version %s, commit %s, branch %s", version, commit, branch)

	// Set up profiling, if requested.
	if cpuprofile != "" {
		log.Println("profiling enabled")
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Printf("unable to create path: %s", err.Error())
		}
		defer f.Close()

		err = pprof.StartCPUProfile(f)
		if err != nil {
			log.Printf("unable to start CPU Profile: %s", err.Error())
		}

		defer pprof.StopCPUProfile()
	}

	// Create and open the store.
	dataPath, err := filepath.Abs(dataPath)
	if err != nil {
		log.Fatalf("failed to determine absolute data path: %s", err.Error())
	}
	dbConf := sql.NewConfig()
	dbConf.DSN = dsn
	dbConf.Memory = inMem
	store := store.New(dbConf, dataPath, raftAddr)
	if err := store.Open(joinAddr == ""); err != nil {
		log.Fatalf("failed to open store: %s", err.Error())
	}

	// If join was specified, make the join request.
	if joinAddr != "" {
		if err := join(joinAddr, noVerify, raftAddr); err != nil {
			log.Fatalf("failed to join node at %s: %s", joinAddr, err.Error())
		}
		log.Println("successfully joined node at", joinAddr)
	}

	// Create the HTTP query server.
	s := httpd.New(httpAddr, store)
	s.CertFile = x509Cert
	s.KeyFile = x509Key
	s.AuthFile = authFile
	s.DisableRedirect = disRedirect
	s.Expvar = expvar
	s.Version = version
	s.Commit = commit
	s.Branch = branch
	if err := s.Start(); err != nil {
		log.Fatalf("failed to start HTTP server: %s", err.Error())

	}

	terminate := make(chan os.Signal, 1)
	signal.Notify(terminate, os.Interrupt)
	<-terminate
	if err := store.Close(); err != nil {
		log.Printf("failed to close store: %s", err.Error())
	}
	log.Println("rqlite server stopped")
}

func join(joinAddr string, skipVerify bool, raftAddr string) error {
	b, err := json.Marshal(map[string]string{"addr": raftAddr})
	if err != nil {
		return err
	}

	// Check for protocol scheme, and insert default if necessary.
	fullAddr := fmt.Sprintf("%s/join", joinAddr)
	if !strings.HasPrefix(joinAddr, "http://") && !strings.HasPrefix(joinAddr, "https://") {
		fullAddr = fmt.Sprintf("http://%s", joinAddr)
	}

	// Enable skipVerify as requested.
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: skipVerify},
	}
	client := &http.Client{Transport: tr}

	// Attempt to join.
	resp, err := client.Post(fullAddr, "application-type/json", bytes.NewReader(b))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("failed to join, node returned: %s", resp.Status)
	}
	defer resp.Body.Close()

	return nil
}
<commit_msg>Display logo on startup<commit_after>/*
rqlite -- a replicated SQLite database.

rqlite is a distributed system that provides a replicated SQLite database.
rqlite is written in Go and uses Raft to achieve consensus across all the
instances of the SQLite databases. rqlite ensures that every change made to
the database is made to a majority of underlying SQLite files, or none-at-all.
*/

package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"runtime/pprof"
	"strings"

	sql "github.com/otoolep/rqlite/db"
	httpd "github.com/otoolep/rqlite/http"
	"github.com/otoolep/rqlite/store"
)

const sqliteDSN = "db.sqlite"

const logo = `
            _ _ _           _
           | (_) |         | |
  _ __ __ _| |_| |_ ___  __| |
 | '__/ _  | | | __/ _ \/ _  |
 | | | (_| | | | ||  __/ (_| |
 |_|  \__, |_|_|\__\___|\__,_|
         | |
         |_|
`

// These variables are populated via the Go linker.
var (
	version = "2"
	commit  string
	branch  string
)

var httpAddr string
var authFile string
var x509Cert string
var x509Key string
var raftAddr string
var joinAddr string
var noVerify bool
var expvar bool
var dsn string
var inMem bool
var disRedirect bool
var showVersion bool
var cpuprofile string

const desc = `rqlite is a distributed system that provides a replicated SQLite database.`

func init() {
	flag.StringVar(&httpAddr, "http", "localhost:4001", "HTTP query server address. Set X.509 cert and key for HTTPS.")
	flag.StringVar(&x509Cert, "x509cert", "", "Path to X.509 certificate")
	flag.StringVar(&x509Key, "x509key", "", "Path to X.509 private key for certificate")
	flag.StringVar(&authFile, "auth", "", "Path to authentication and authorization file. If not set, not enabled.")
	flag.StringVar(&raftAddr, "raft", "localhost:4002", "Raft communication bind address")
	flag.StringVar(&joinAddr, "join", "", "protocol://host:port of leader to join")
	flag.BoolVar(&noVerify, "noverify", false, "Skip verification of any HTTPS cert when joining")
	flag.BoolVar(&expvar, "expvar", true, "Serve expvar data on HTTP server")
	flag.StringVar(&dsn, "dsn", "", `SQLite DSN parameters. E.g. "cache=shared&mode=memory"`)
	flag.BoolVar(&inMem, "mem", false, "Use an in-memory database")
	flag.BoolVar(&disRedirect, "noredir", true, "Disable leader-redirect")
	flag.BoolVar(&showVersion, "version", false, "Show version information and exit")
	flag.StringVar(&cpuprofile, "cpuprofile", "", "Write CPU profile to file")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "\n%s\n\n", desc)
		fmt.Fprintf(os.Stderr, "Usage: %s [arguments] <data directory>\n", os.Args[0])
		flag.PrintDefaults()
	}

	// If commit, branch, or build time are not set, make that clear.
	if commit == "" {
		commit = "unknown"
	}
	if branch == "" {
		branch = "unknown"
	}
}

func main() {
	flag.Parse()

	if showVersion {
		fmt.Printf("rqlited version %s (commit %s)\n", version, commit)
		os.Exit(0)
	}

	// Ensure the data path is set.
	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	dataPath := flag.Arg(0)

	// Display logo.
	fmt.Println(logo)

	// Configure logging and pump out initial message.
	log.SetFlags(log.LstdFlags)
	log.SetPrefix("[rqlited] ")
	log.Printf("rqlited starting, version %s, commit %s, branch %s", version, commit, branch)

	// Set up profiling, if requested.
	if cpuprofile != "" {
		log.Println("profiling enabled")
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Printf("unable to create path: %s", err.Error())
		}
		defer f.Close()

		err = pprof.StartCPUProfile(f)
		if err != nil {
			log.Fatalf("unable to start CPU Profile: %s", err.Error())
		}

		defer pprof.StopCPUProfile()
	}

	// Create and open the store.
	dataPath, err := filepath.Abs(dataPath)
	if err != nil {
		log.Fatalf("failed to determine absolute data path: %s", err.Error())
	}
	dbConf := sql.NewConfig()
	dbConf.DSN = dsn
	dbConf.Memory = inMem
	store := store.New(dbConf, dataPath, raftAddr)
	if err := store.Open(joinAddr == ""); err != nil {
		log.Fatalf("failed to open store: %s", err.Error())
	}

	// If join was specified, make the join request.
	if joinAddr != "" {
		if err := join(joinAddr, noVerify, raftAddr); err != nil {
			log.Fatalf("failed to join node at %s: %s", joinAddr, err.Error())
		}
		log.Println("successfully joined node at", joinAddr)
	}

	// Create the HTTP query server.
	s := httpd.New(httpAddr, store)
	s.CertFile = x509Cert
	s.KeyFile = x509Key
	s.AuthFile = authFile
	s.DisableRedirect = disRedirect
	s.Expvar = expvar
	s.Version = version
	s.Commit = commit
	s.Branch = branch
	if err := s.Start(); err != nil {
		log.Fatalf("failed to start HTTP server: %s", err.Error())

	}

	terminate := make(chan os.Signal, 1)
	signal.Notify(terminate, os.Interrupt)
	<-terminate
	if err := store.Close(); err != nil {
		log.Printf("failed to close store: %s", err.Error())
	}
	log.Println("rqlite server stopped")
}

func join(joinAddr string, skipVerify bool, raftAddr string) error {
	b, err := json.Marshal(map[string]string{"addr": raftAddr})
	if err != nil {
		return err
	}

	// Check for protocol scheme, and insert default if necessary.
	fullAddr := fmt.Sprintf("%s/join", joinAddr)
	if !strings.HasPrefix(joinAddr, "http://") && !strings.HasPrefix(joinAddr, "https://") {
		fullAddr = fmt.Sprintf("http://%s", joinAddr)
	}

	// Enable skipVerify as requested.
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: skipVerify},
	}
	client := &http.Client{Transport: tr}

	// Attempt to join.
	resp, err := client.Post(fullAddr, "application-type/json", bytes.NewReader(b))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("failed to join, node returned: %s", resp.Status)
	}
	defer resp.Body.Close()

	return nil
}
<|endoftext|>


<commit_before>/*
 * s3verify (C) 2016 Minio, Inc.
 *
 * 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 cmd

var awsS3EndpointMap = map[string]string{
	"us-east-1":      "s3.amazonaws.com",
	"us-west-1":      "s3-us-west-1.amazonaws.com",
	"us-west-2":      "s3-us-west-2.amazonaws.com",
	"ap-south-1":     "s3.ap-south-1.amazonaws.com",
	"ap-southeast-1": "s3-ap-southeast-1.amazonaws.com",
	"ap-southeast-2": "s3-ap-southeast-2.amazonaws.com",
	"ap-northeast-1": "s3-ap-northeast-1.amazonaws.com",
	"ap-northeast-2": "s3-ap-northeast-2.amazonaws.com",
	"sa-east-1":      "s3-sa-east-1.amazonaws.com",
	"eu-central-1":   "s3.eu-central-1.amazonaws.com",
	"eu-west-1":      "s3-ue-west-1.amazonaws.com",
	"cn-north-1":     "s3.cn-north-1.amazonaws.com.cn",
}

// getS3Endpoint gets Amazon S3 endpoint based on location.
func getS3Endpoint(bucketLocation string) (s3Endpoint string) {
	s3Endpoint, ok := awsS3EndpointMap[bucketLocation]
	if !ok {
		// Default to 's3.amazonaws.com' endpoint.
		s3Endpoint = "s3.amazonaws.com"
	}
	return s3Endpoint
}
<commit_msg>Endpoints: fix typo in eu-west-1 region string (#212)<commit_after>/*
 * s3verify (C) 2016 Minio, Inc.
 *
 * 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 cmd

var awsS3EndpointMap = map[string]string{
	"us-east-1":      "s3.amazonaws.com",
	"us-west-1":      "s3-us-west-1.amazonaws.com",
	"us-west-2":      "s3-us-west-2.amazonaws.com",
	"ap-south-1":     "s3.ap-south-1.amazonaws.com",
	"ap-southeast-1": "s3-ap-southeast-1.amazonaws.com",
	"ap-southeast-2": "s3-ap-southeast-2.amazonaws.com",
	"ap-northeast-1": "s3-ap-northeast-1.amazonaws.com",
	"ap-northeast-2": "s3-ap-northeast-2.amazonaws.com",
	"sa-east-1":      "s3-sa-east-1.amazonaws.com",
	"eu-central-1":   "s3.eu-central-1.amazonaws.com",
	"eu-west-1":      "s3-eu-west-1.amazonaws.com",
	"cn-north-1":     "s3.cn-north-1.amazonaws.com.cn",
}

// getS3Endpoint gets Amazon S3 endpoint based on location.
func getS3Endpoint(bucketLocation string) (s3Endpoint string) {
	s3Endpoint, ok := awsS3EndpointMap[bucketLocation]
	if !ok {
		// Default to 's3.amazonaws.com' endpoint.
		s3Endpoint = "s3.amazonaws.com"
	}
	return s3Endpoint
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
)

const crUsageString = `xb copyright [options] <path>....

The xb copyright command adds a copyright remark to all go files below path.

  -h  prints this message and exits
`

func crUsage(w io.Writer) {
	fmt.Fprint(w, crUsageString)
}

func copyright() {
	cmdName := os.Args[0]
	log.SetPrefix(fmt.Sprintf("%s: ", cmdName))
	log.SetFlags(0)

	flag.CommandLine = flag.NewFlagSet(cmdName, flag.ExitOnError)
	flag.Usage = func() { crUsage(os.Stderr); os.Exit(1) }

	help := flag.Bool("h", false, "")

	flag.Parse()

	if *help {
		crUsage(os.Stdout)
		os.Exit(0)
	}

	for _, path := range flag.Args() {
		fi, err := os.Stat(path)
		if err != nil {
			log.Print(err)
			continue
		}
		if !fi.IsDir() {
			log.Printf("%s is not a directory", path)
			continue
		}
		log.Printf("handle %s", path)
	}
}
<commit_msg>xb copyright: finds now files to add copyrights to<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const crUsageString = `xb copyright [options] <path>....

The xb copyright command adds a copyright remark to all go files below path.

  -h  prints this message and exits
`

func crUsage(w io.Writer) {
	fmt.Fprint(w, crUsageString)
}

func addCopyright(path string) error {
	fmt.Println(path)
	return nil
}

func walkCopyrights(path string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}
	if info.IsDir() {
		return nil
	}
	if !strings.HasSuffix(info.Name(), ".go") {
		return nil
	}
	return addCopyright(path)
}

func copyright() {
	cmdName := os.Args[0]
	log.SetPrefix(fmt.Sprintf("%s: ", cmdName))
	log.SetFlags(0)

	flag.CommandLine = flag.NewFlagSet(cmdName, flag.ExitOnError)
	flag.Usage = func() { crUsage(os.Stderr); os.Exit(1) }

	help := flag.Bool("h", false, "")

	flag.Parse()

	if *help {
		crUsage(os.Stdout)
		os.Exit(0)
	}

	for _, path := range flag.Args() {
		fi, err := os.Stat(path)
		if err != nil {
			log.Print(err)
			continue
		}
		if !fi.IsDir() {
			log.Printf("%s is not a directory", path)
			continue
		}
		if err = filepath.Walk(path, walkCopyrights); err != nil {
			log.Fatalf("%s error %s", path, err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"./slackboard"
	"flag"
	"github.com/Sirupsen/logrus"
	statsGo "github.com/fukata/golang-stats-api-handler"
	"html/template"
	"log"
	"net"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"
)

func main() {

	version := flag.Bool("v", false, "slackboard version")
	confPath := flag.String("c", "", "configuration file for slackboard")
	flag.Parse()

	if *version {
		slackboard.PrintVersion()
		os.Exit(0)
	}

	// Set concurrency
	runtime.GOMAXPROCS(runtime.NumCPU())

	// init logger
	slackboard.LogAccess = logrus.New()
	slackboard.LogError = logrus.New()

	slackboard.LogAccess.Formatter = new(slackboard.SlackboardFormatter)
	slackboard.LogError.Formatter = new(slackboard.SlackboardFormatter)

	// Load conf
	slackboard.ConfSlackboard = slackboard.BuildDefaultConf()
	err := slackboard.LoadConf(*confPath, &slackboard.ConfSlackboard)
	if err != nil {
		log.Fatal(err.Error())
	}

	// set logger
	err = slackboard.SetLogLevel(slackboard.LogAccess, "info")
	if err != nil {
		log.Fatal(err)
	}
	err = slackboard.SetLogLevel(slackboard.LogError, slackboard.ConfSlackboard.Log.Level)
	if err != nil {
		log.Fatal(err)
	}
	err = slackboard.SetLogOut(slackboard.LogAccess, slackboard.ConfSlackboard.Log.AccessLog)
	if err != nil {
		log.Fatal(err)
	}
	err = slackboard.SetLogOut(slackboard.LogError, slackboard.ConfSlackboard.Log.ErrorLog)
	if err != nil {
		log.Fatal(err)
	}

	slackboard.IndexTemplate = template.Must(template.ParseFiles("web/index.html"))

	http.HandleFunc("/notify", slackboard.NotifyHandler)
	http.HandleFunc("/app/config", slackboard.ConfigAppHandler)
	http.HandleFunc("/stats/go", statsGo.Handler)
	slackboard.SetupUI()

	// Listen TCP Port
	if _, err := strconv.Atoi(slackboard.ConfSlackboard.Core.Port); err == nil {
		http.ListenAndServe(":"+slackboard.ConfSlackboard.Core.Port, nil)
	}

	// Listen UNIX Socket
	if strings.HasPrefix(slackboard.ConfSlackboard.Core.Port, "unix:/") {
		sockPath := slackboard.ConfSlackboard.Core.Port[5:]
		fi, err := os.Lstat(sockPath)
		if err == nil && (fi.Mode()&os.ModeSocket) == os.ModeSocket {
			err := os.Remove(sockPath)
			if err != nil {
				log.Fatal("failed to remove " + sockPath)
			}
		}
		l, err := net.Listen("unix", sockPath)
		if err != nil {
			log.Fatal("failed to listen: " + sockPath)
		}
		http.Serve(l, nil)
	}

	log.Fatal("port parameter is invalid: " + slackboard.ConfSlackboard.Core.Port)

}
<commit_msg>Removed redundant process.<commit_after>package main

import (
	"./slackboard"
	"flag"
	"github.com/Sirupsen/logrus"
	statsGo "github.com/fukata/golang-stats-api-handler"
	"log"
	"net"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"
)

func main() {

	version := flag.Bool("v", false, "slackboard version")
	confPath := flag.String("c", "", "configuration file for slackboard")
	flag.Parse()

	if *version {
		slackboard.PrintVersion()
		os.Exit(0)
	}

	// Set concurrency
	runtime.GOMAXPROCS(runtime.NumCPU())

	// init logger
	slackboard.LogAccess = logrus.New()
	slackboard.LogError = logrus.New()

	slackboard.LogAccess.Formatter = new(slackboard.SlackboardFormatter)
	slackboard.LogError.Formatter = new(slackboard.SlackboardFormatter)

	// Load conf
	slackboard.ConfSlackboard = slackboard.BuildDefaultConf()
	err := slackboard.LoadConf(*confPath, &slackboard.ConfSlackboard)
	if err != nil {
		log.Fatal(err.Error())
	}

	// set logger
	err = slackboard.SetLogLevel(slackboard.LogAccess, "info")
	if err != nil {
		log.Fatal(err)
	}
	err = slackboard.SetLogLevel(slackboard.LogError, slackboard.ConfSlackboard.Log.Level)
	if err != nil {
		log.Fatal(err)
	}
	err = slackboard.SetLogOut(slackboard.LogAccess, slackboard.ConfSlackboard.Log.AccessLog)
	if err != nil {
		log.Fatal(err)
	}
	err = slackboard.SetLogOut(slackboard.LogError, slackboard.ConfSlackboard.Log.ErrorLog)
	if err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/notify", slackboard.NotifyHandler)
	http.HandleFunc("/app/config", slackboard.ConfigAppHandler)
	http.HandleFunc("/stats/go", statsGo.Handler)
	slackboard.SetupUI()

	// Listen TCP Port
	if _, err := strconv.Atoi(slackboard.ConfSlackboard.Core.Port); err == nil {
		http.ListenAndServe(":"+slackboard.ConfSlackboard.Core.Port, nil)
	}

	// Listen UNIX Socket
	if strings.HasPrefix(slackboard.ConfSlackboard.Core.Port, "unix:/") {
		sockPath := slackboard.ConfSlackboard.Core.Port[5:]
		fi, err := os.Lstat(sockPath)
		if err == nil && (fi.Mode()&os.ModeSocket) == os.ModeSocket {
			err := os.Remove(sockPath)
			if err != nil {
				log.Fatal("failed to remove " + sockPath)
			}
		}
		l, err := net.Listen("unix", sockPath)
		if err != nil {
			log.Fatal("failed to listen: " + sockPath)
		}
		http.Serve(l, nil)
	}

	log.Fatal("port parameter is invalid: " + slackboard.ConfSlackboard.Core.Port)

}
<|endoftext|>