<commit_before>package colonycore

import (
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	"io/ioutil"
	"os"
	// "os/exec"
	"path/filepath"
	// "runtime"
	"strings"
)

type Widget struct {
	orm.ModelBase
	ID    string `json:"_id"`
	Title string `json:"title"`
	// DataSourceID []string            `json:"dataSourceId"`
	DataSource  []*DataSourceWidget `json:"dataSource"`
	Description string              `json:"description"`
	Config      []*Config           `json:"config"`
	Params      toolkit.M           `json:"params"`
	Path        string
}

type DataSourceWidget struct {
	ID   string      `json:"_id"`
	Data []toolkit.M `json:"data"`
}

type Config struct {
	orm.ModelBase
	data []toolkit.M `json:"data"`
}

func (w *Widget) TableName() string {
	return "widgets"
}

func (w *Widget) RecordID() interface{} {
	return w.ID
}

func (w *Widget) Get(search string) ([]Widget, error) {
	var query *dbox.Filter

	if search != "" {
		query = dbox.Contains("_id", search)
	}

	data := []Widget{}
	cursor, err := Find(new(Widget), query)
	if err != nil {
		return nil, err
	}
	if err := cursor.Fetch(&data, 0, false); err != nil {
		return nil, err
	}
	defer cursor.Close()
	return data, nil
}

func (w *Widget) GetById() error {
	if err := Get(w, w.ID); err != nil {
		return err
	}
	return nil
}

func (w *Widget) Save() error {
	if err := Save(w); err != nil {
		return err
	}
	return nil
}

func checkDir(basepath string, scanDir string, dirName string) error {
	dirList, err := ioutil.ReadDir(scanDir)
	if err != nil {
		return err
	}

	if toolkit.SliceLen(dirList) == 1 {
		for _, f := range dirList {
			if f.IsDir() {
				oldpath := filepath.Join(scanDir, f.Name())
				temp_oldpath := filepath.Join(scanDir, dirName)
				if err := os.Rename(oldpath, temp_oldpath); err != nil {
					return err
				}
				if err := toolkit.ZipCompress(temp_oldpath, scanDir+".zip"); err != nil {
					return err
				}
				if err := os.RemoveAll(scanDir); err != nil {
					return err
				}
				if err := toolkit.ZipExtract(scanDir+".zip", basepath); err != nil {
					return err
				}
				if err := os.Remove(scanDir + ".zip"); err != nil {
					return err
				}
			}
		}
	}

	return nil
}

func (w *Widget) ExtractFile(compressedSource string, fileName string) error {
	compressedFile := filepath.Join(compressedSource, fileName)
	extractDest := filepath.Join(compressedSource, w.ID)

	if err := os.RemoveAll(extractDest); err != nil {
		return err
	}

	if strings.Contains(fileName, ".tar.gz") {
		if err := toolkit.TarGzExtract(compressedFile, extractDest); err != nil {
			return err
		}
	} else if strings.Contains(fileName, ".gz") {
		if err := toolkit.GzExtract(compressedFile, extractDest); err != nil {
			return err
		}
	} else if strings.Contains(fileName, ".tar") {
		if err := toolkit.TarExtract(compressedFile, extractDest); err != nil {
			return err
		}
	} else if strings.Contains(fileName, ".zip") {
		if err := toolkit.ZipExtract(compressedFile, extractDest); err != nil {
			return err
		}
	}

	if err := os.Remove(compressedFile); err != nil {
		return err
	}

	getConfigFile := filepath.Join(extractDest, "config.json")
	content, err := ioutil.ReadFile(getConfigFile)
	if err != nil {
		return err
	}

	// contentstring := string(content)
	var result = Config{}.data
	toolkit.Unjson(content, &result)
	toolkit.Println(result, string(content))
	// checkDir(compressedSource, extractDest, w.ID)

	return nil
}

func (w *Widget) Delete(compressedSource string) error {
	extractDest := filepath.Join(compressedSource, w.ID)
	if err := Delete(w); err != nil {
		return err
	}

	if err := os.RemoveAll(extractDest); err != nil {
		return err
	}
	return nil
}
<commit_msg>update widget model<commit_after>package colonycore

import (
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

type Widget struct {
	orm.ModelBase
	ID           string     `json:"_id"`
	Title        string     `json:"title"`
	DataSourceId []string   `json:"dataSourceId"`
	Description  string     `json:"description"`
	Config       toolkit.Ms `json:"config"`
	Params       toolkit.M  `json:"params"`
	URL          string     `json:"url"`
}

type DataSourceWidget struct {
	ID   string      `json:"_id"`
	Data []toolkit.M `json:"data"`
}

func (w *Widget) TableName() string {
	return "widgets"
}

func (w *Widget) RecordID() interface{} {
	return w.ID
}

func (w *Widget) Get(search string) ([]Widget, error) {
	var query *dbox.Filter

	if search != "" {
		query = dbox.Contains("_id", search)
	}

	data := []Widget{}
	cursor, err := Find(new(Widget), query)
	if err != nil {
		return nil, err
	}
	if err := cursor.Fetch(&data, 0, false); err != nil {
		return nil, err
	}
	defer cursor.Close()
	return data, nil
}

func (w *Widget) GetById() error {
	if err := Get(w, w.ID); err != nil {
		return err
	}
	return nil
}

func (w *Widget) Save() error {
	if err := Save(w); err != nil {
		return err
	}
	return nil
}

func GetPath(root string) (string, error) {
	absRoot, err := filepath.Abs(root)
	if err != nil {
		return "", err
	}
	var _path string
	var indexPath []string
	var configPath []string
	var assetPath []string
	walkFunc := func(path string, info os.FileInfo, err error) error {
		_path, filename := filepath.Split(path)
		if strings.Compare(filename, "index.html") == 0 {
			indexPath = append(indexPath, _path)
		}
		if strings.Compare(filename, "config.json") == 0 {
			configPath = append(configPath, _path)
		}

		if strings.Compare(filename, "assets") == 0 {
			assetPath = append(assetPath, _path)
		}
		return nil
	}
	if err = filepath.Walk(absRoot, walkFunc); err != nil {
		if err.Error() == "found" {
			return _path, nil
		} else {
			return "", err
		}
	}

	for _, valIndex := range indexPath {
		for _, valConfig := range configPath {
			for _, valAsset := range assetPath {
				if valIndex == valConfig && valConfig == valAsset {
					_path = valConfig
					break
				}
			}

		}
	}
	return _path, nil
}

func (w *Widget) ExtractFile(compressedSource string, fileName string) (toolkit.Ms, error) {
	compressedFile := filepath.Join(compressedSource, fileName)
	extractDest := filepath.Join(compressedSource, w.ID)

	if err := os.RemoveAll(extractDest); err != nil {
		return nil, err
	}

	if strings.Contains(fileName, ".tar.gz") {
		if err := toolkit.TarGzExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".gz") {
		if err := toolkit.GzExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".tar") {
		if err := toolkit.TarExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".zip") {
		if err := toolkit.ZipExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	}

	if err := os.Remove(compressedFile); err != nil {
		return nil, err
	}

	path, err := GetPath(extractDest)
	if err != nil {
		return nil, err
	}

	urlPath := filepath.ToSlash(path)
	splitPath := strings.SplitAfter(urlPath, "/data-root/widget/")
	w.URL = strings.Join([]string{w.URL, "res-widget", splitPath[1]}, "/")

	getConfigFile := filepath.Join(path, "config.json")
	content, err := ioutil.ReadFile(getConfigFile)
	if err != nil {
		return nil, err
	}

	result := toolkit.Ms{}
	err = toolkit.Unjson(content, &result)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (w *Widget) Delete(compressedSource string) error {
	extractDest := filepath.Join(compressedSource, w.ID)
	if err := Delete(w); err != nil {
		return err
	}

	if err := os.RemoveAll(extractDest); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package files

import (
	"path/filepath"

	"github.com/juju/errors"
)

// TODO(ericsnow) Pull these from authoritative sources:
var (
	dataDir        = "/var/lib/juju"
	startupDir     = "/etc/init"
	loggingConfDir = "/etc/rsyslog.d"
	logsDir        = "/var/log/juju"
	sshDir         = "/home/ubuntu/.ssh"

	machinesConfs = "jujud-machine-*.conf"
	agentsDir     = "agents"
	agentsConfs   = "machine-*"
	loggingConfs  = "*juju.conf"
	toolsDir      = "tools"

	sshIdentFile   = "system-identity"
	nonceFile      = "nonce.txt"
	allMachinesLog = "all-machines.log"
	machine0Log    = "machine-0.log"
	authKeysFile   = "authorized_keys"

	dbStartupConf = "juju-db.conf"
	dbPEM         = "server.pem"
	dbSecret      = "shared-secret"
)

// GetFilesToBackUp returns the paths that should be included in the
// backup archive.
func GetFilesToBackUp(rootDir string) ([]string, error) {
	var glob string

	glob = filepath.Join(rootDir, startupDir, machinesConfs)
	initMachineConfs, err := filepath.Glob(glob)
	if err != nil {
		return nil, errors.Annotate(err, "failed to fetch machine init files")
	}

	glob = filepath.Join(rootDir, dataDir, agentsDir, agentsConfs)
	agentConfs, err := filepath.Glob(glob)
	if err != nil {
		return nil, errors.Annotate(err, "failed to fetch agent config files")
	}

	glob = filepath.Join(rootDir, loggingConfDir, loggingConfs)
	jujuLogConfs, err := filepath.Glob(glob)
	if err != nil {
		return nil, errors.Annotate(err, "failed to fetch juju log conf files")
	}

	backupFiles := []string{
		filepath.Join(rootDir, dataDir, toolsDir),

		filepath.Join(rootDir, dataDir, sshIdentFile),
		filepath.Join(rootDir, dataDir, nonceFile),
		filepath.Join(rootDir, logsDir, allMachinesLog),
		filepath.Join(rootDir, logsDir, machine0Log),
		filepath.Join(rootDir, sshDir, authKeysFile),

		filepath.Join(rootDir, startupDir, dbStartupConf),
		filepath.Join(rootDir, dataDir, dbPEM),
		filepath.Join(rootDir, dataDir, dbSecret),
	}
	backupFiles = append(backupFiles, initMachineConfs...)
	backupFiles = append(backupFiles, agentConfs...)
	backupFiles = append(backupFiles, jujuLogConfs...)
	return backupFiles, nil
}
<commit_msg>Mention the single-source-of-truth for juju paths.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package files

import (
	"path/filepath"

	"github.com/juju/errors"
)

// TODO(ericsnow) Pull these from authoritative sources (see
// github.com/juju/juju/juju/paths, etc.):
var (
	dataDir        = "/var/lib/juju"
	startupDir     = "/etc/init"
	loggingConfDir = "/etc/rsyslog.d"
	logsDir        = "/var/log/juju"
	sshDir         = "/home/ubuntu/.ssh"

	machinesConfs = "jujud-machine-*.conf"
	agentsDir     = "agents"
	agentsConfs   = "machine-*"
	loggingConfs  = "*juju.conf"
	toolsDir      = "tools"

	sshIdentFile   = "system-identity"
	nonceFile      = "nonce.txt"
	allMachinesLog = "all-machines.log"
	machine0Log    = "machine-0.log"
	authKeysFile   = "authorized_keys"

	dbStartupConf = "juju-db.conf"
	dbPEM         = "server.pem"
	dbSecret      = "shared-secret"
)

// GetFilesToBackUp returns the paths that should be included in the
// backup archive.
func GetFilesToBackUp(rootDir string) ([]string, error) {
	var glob string

	glob = filepath.Join(rootDir, startupDir, machinesConfs)
	initMachineConfs, err := filepath.Glob(glob)
	if err != nil {
		return nil, errors.Annotate(err, "failed to fetch machine init files")
	}

	glob = filepath.Join(rootDir, dataDir, agentsDir, agentsConfs)
	agentConfs, err := filepath.Glob(glob)
	if err != nil {
		return nil, errors.Annotate(err, "failed to fetch agent config files")
	}

	glob = filepath.Join(rootDir, loggingConfDir, loggingConfs)
	jujuLogConfs, err := filepath.Glob(glob)
	if err != nil {
		return nil, errors.Annotate(err, "failed to fetch juju log conf files")
	}

	backupFiles := []string{
		filepath.Join(rootDir, dataDir, toolsDir),

		filepath.Join(rootDir, dataDir, sshIdentFile),
		filepath.Join(rootDir, dataDir, nonceFile),
		filepath.Join(rootDir, logsDir, allMachinesLog),
		filepath.Join(rootDir, logsDir, machine0Log),
		filepath.Join(rootDir, sshDir, authKeysFile),

		filepath.Join(rootDir, startupDir, dbStartupConf),
		filepath.Join(rootDir, dataDir, dbPEM),
		filepath.Join(rootDir, dataDir, dbSecret),
	}
	backupFiles = append(backupFiles, initMachineConfs...)
	backupFiles = append(backupFiles, agentConfs...)
	backupFiles = append(backupFiles, jujuLogConfs...)
	return backupFiles, nil
}
<|endoftext|>


<commit_before>//go:build integration
// +build integration

/*
Copyright 2020 The Kubernetes Authors All rights reserved.

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 integration

import (
	"context"
	"encoding/json"
	"os/exec"
	"strings"
	"testing"

	"k8s.io/minikube/cmd/minikube/cmd"
)

// TestPause tests minikube pause functionality
func TestPause(t *testing.T) {
	MaybeParallel(t)

	type validateFunc func(context.Context, *testing.T, string)
	profile := UniqueProfileName("pause")
	ctx, cancel := context.WithTimeout(context.Background(), Minutes(15))
	defer Cleanup(t, profile, cancel)

	// Serial tests
	t.Run("serial", func(t *testing.T) {
		tests := []struct {
			name      string
			validator validateFunc
		}{
			{"Start", validateFreshStart},
			{"SecondStartNoReconfiguration", validateStartNoReconfigure},
			{"Pause", validatePause},
			{"VerifyStatus", validateStatus},
			{"Unpause", validateUnpause},
			{"PauseAgain", validatePause},
			{"DeletePaused", validateDelete},
			{"VerifyDeletedResources", validateVerifyDeleted},
		}
		for _, tc := range tests {
			tc := tc

			if ctx.Err() == context.DeadlineExceeded {
				t.Fatalf("Unable to run more tests (deadline exceeded)")
			}

			t.Run(tc.name, func(t *testing.T) {
				tc.validator(ctx, t, profile)
				if t.Failed() && *postMortemLogs {
					PostMortemLogs(t, profile)
				}
			})
		}
	})
}

// validateFreshStart just starts a new minikube cluster
func validateFreshStart(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := append([]string{"start", "-p", profile, "--memory=2048", "--install-addons=false", "--wait=all"}, StartArgs()...)
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Fatalf("failed to start minikube with args: %q : %v", rr.Command(), err)
	}
}

// validateStartNoReconfigure validates that starting a running cluster does not invoke reconfiguration
func validateStartNoReconfigure(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := []string{"start", "-p", profile, "--alsologtostderr", "-v=1"}
	args = append(args, StartArgs()...)
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Fatalf("failed to second start a running minikube with args: %q : %v", rr.Command(), err)
	}

	if !NoneDriver() {
		softLog := "The running cluster does not require reconfiguration"
		if !strings.Contains(rr.Output(), softLog) {
			t.Errorf("expected the second start log output to include %q but got: %s", softLog, rr.Output())
		}
	}
}

// validatePause runs minikube pause
func validatePause(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := []string{"pause", "-p", profile, "--alsologtostderr", "-v=5"}
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Errorf("failed to pause minikube with args: %q : %v", rr.Command(), err)
	}
}

// validateUnpause runs minikube unpause
func validateUnpause(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := []string{"unpause", "-p", profile, "--alsologtostderr", "-v=5"}
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Errorf("failed to unpause minikube with args: %q : %v", rr.Command(), err)
	}
}

// validateDelete deletes the unpaused cluster
func validateDelete(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := []string{"delete", "-p", profile, "--alsologtostderr", "-v=5"}
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Errorf("failed to delete minikube with args: %q : %v", rr.Command(), err)
	}
}

// validateVerifyDeleted makes sure no left over left after deleting a profile such as containers or volumes
func validateVerifyDeleted(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	rr, err := Run(t, exec.CommandContext(ctx, Target(), "profile", "list", "--output", "json"))
	if err != nil {
		t.Errorf("failed to list profiles with json format after it was deleted. args %q: %v", rr.Command(), err)
	}

	var jsonObject map[string][]map[string]interface{}
	if err := json.Unmarshal(rr.Stdout.Bytes(), &jsonObject); err != nil {
		t.Errorf("failed to decode json from profile list: args %q: %v", rr.Command(), err)
	}
	validProfiles := jsonObject["valid"]
	profileExists := false
	for _, profileObject := range validProfiles {
		if profileObject["Name"] == profile {
			profileExists = true
			break
		}
	}
	if profileExists {
		t.Errorf("expected the deleted profile %q not to show up in profile list but it does! output: %s . args: %q", profile, rr.Stdout.String(), rr.Command())
	}

	if KicDriver() {
		bin := "docker"
		if PodmanDriver() {
			bin = "podman"
		}
		rr, err := Run(t, exec.CommandContext(ctx, bin, "ps", "-a"))
		if err == nil && strings.Contains(rr.Output(), profile) {
			t.Errorf("expected container %q not to exist in output of %s but it does output: %s.", profile, rr.Command(), rr.Output())
		}

		rr, err = Run(t, exec.CommandContext(ctx, bin, "volume", "inspect", profile))
		if err == nil {
			t.Errorf("expected to see error and volume %q to not exist after deletion but got no error and this output: %s", rr.Command(), rr.Output())
		}

		rr, err = Run(t, exec.CommandContext(ctx, "sudo", bin, "network", "ls"))
		if err != nil {
			t.Errorf("failed to get list of networks: %v", err)
		}
		if strings.Contains(rr.Output(), profile) {
			t.Errorf("expected network %q to not exist after deletion but contained: %s", profile, rr.Output())
		}
	}

}

// validateStatus makes sure paused clusters show up in minikube status correctly
func validateStatus(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	statusOutput := runStatusCmd(ctx, t, profile, false)
	var cs cmd.ClusterState
	if err := json.Unmarshal(statusOutput, &cs); err != nil {
		t.Fatalf("unmarshalling: %v", err)
	}
	// verify the status looks as we expect
	if cs.StatusCode != cmd.Paused {
		t.Fatalf("incorrect status code: %v", cs.StatusCode)
	}
	if cs.StatusName != "Paused" {
		t.Fatalf("incorrect status name: %v", cs.StatusName)
	}
}
<commit_msg>removed one off sudo command from test<commit_after>//go:build integration
// +build integration

/*
Copyright 2020 The Kubernetes Authors All rights reserved.

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 integration

import (
	"context"
	"encoding/json"
	"os/exec"
	"strings"
	"testing"

	"k8s.io/minikube/cmd/minikube/cmd"
)

// TestPause tests minikube pause functionality
func TestPause(t *testing.T) {
	MaybeParallel(t)

	type validateFunc func(context.Context, *testing.T, string)
	profile := UniqueProfileName("pause")
	ctx, cancel := context.WithTimeout(context.Background(), Minutes(15))
	defer Cleanup(t, profile, cancel)

	// Serial tests
	t.Run("serial", func(t *testing.T) {
		tests := []struct {
			name      string
			validator validateFunc
		}{
			{"Start", validateFreshStart},
			{"SecondStartNoReconfiguration", validateStartNoReconfigure},
			{"Pause", validatePause},
			{"VerifyStatus", validateStatus},
			{"Unpause", validateUnpause},
			{"PauseAgain", validatePause},
			{"DeletePaused", validateDelete},
			{"VerifyDeletedResources", validateVerifyDeleted},
		}
		for _, tc := range tests {
			tc := tc

			if ctx.Err() == context.DeadlineExceeded {
				t.Fatalf("Unable to run more tests (deadline exceeded)")
			}

			t.Run(tc.name, func(t *testing.T) {
				tc.validator(ctx, t, profile)
				if t.Failed() && *postMortemLogs {
					PostMortemLogs(t, profile)
				}
			})
		}
	})
}

// validateFreshStart just starts a new minikube cluster
func validateFreshStart(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := append([]string{"start", "-p", profile, "--memory=2048", "--install-addons=false", "--wait=all"}, StartArgs()...)
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Fatalf("failed to start minikube with args: %q : %v", rr.Command(), err)
	}
}

// validateStartNoReconfigure validates that starting a running cluster does not invoke reconfiguration
func validateStartNoReconfigure(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := []string{"start", "-p", profile, "--alsologtostderr", "-v=1"}
	args = append(args, StartArgs()...)
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Fatalf("failed to second start a running minikube with args: %q : %v", rr.Command(), err)
	}

	if !NoneDriver() {
		softLog := "The running cluster does not require reconfiguration"
		if !strings.Contains(rr.Output(), softLog) {
			t.Errorf("expected the second start log output to include %q but got: %s", softLog, rr.Output())
		}
	}
}

// validatePause runs minikube pause
func validatePause(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := []string{"pause", "-p", profile, "--alsologtostderr", "-v=5"}
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Errorf("failed to pause minikube with args: %q : %v", rr.Command(), err)
	}
}

// validateUnpause runs minikube unpause
func validateUnpause(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := []string{"unpause", "-p", profile, "--alsologtostderr", "-v=5"}
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Errorf("failed to unpause minikube with args: %q : %v", rr.Command(), err)
	}
}

// validateDelete deletes the unpaused cluster
func validateDelete(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	args := []string{"delete", "-p", profile, "--alsologtostderr", "-v=5"}
	rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
	if err != nil {
		t.Errorf("failed to delete minikube with args: %q : %v", rr.Command(), err)
	}
}

// validateVerifyDeleted makes sure no left over left after deleting a profile such as containers or volumes
func validateVerifyDeleted(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	rr, err := Run(t, exec.CommandContext(ctx, Target(), "profile", "list", "--output", "json"))
	if err != nil {
		t.Errorf("failed to list profiles with json format after it was deleted. args %q: %v", rr.Command(), err)
	}

	var jsonObject map[string][]map[string]interface{}
	if err := json.Unmarshal(rr.Stdout.Bytes(), &jsonObject); err != nil {
		t.Errorf("failed to decode json from profile list: args %q: %v", rr.Command(), err)
	}
	validProfiles := jsonObject["valid"]
	profileExists := false
	for _, profileObject := range validProfiles {
		if profileObject["Name"] == profile {
			profileExists = true
			break
		}
	}
	if profileExists {
		t.Errorf("expected the deleted profile %q not to show up in profile list but it does! output: %s . args: %q", profile, rr.Stdout.String(), rr.Command())
	}

	if KicDriver() {
		bin := "docker"
		if PodmanDriver() {
			bin = "podman"
		}
		rr, err := Run(t, exec.CommandContext(ctx, bin, "ps", "-a"))
		if err == nil && strings.Contains(rr.Output(), profile) {
			t.Errorf("expected container %q not to exist in output of %s but it does output: %s.", profile, rr.Command(), rr.Output())
		}

		rr, err = Run(t, exec.CommandContext(ctx, bin, "volume", "inspect", profile))
		if err == nil {
			t.Errorf("expected to see error and volume %q to not exist after deletion but got no error and this output: %s", rr.Command(), rr.Output())
		}

		rr, err = Run(t, exec.CommandContext(ctx, bin, "network", "ls"))
		if err != nil {
			t.Errorf("failed to get list of networks: %v", err)
		}
		if strings.Contains(rr.Output(), profile) {
			t.Errorf("expected network %q to not exist after deletion but contained: %s", profile, rr.Output())
		}
	}

}

// validateStatus makes sure paused clusters show up in minikube status correctly
func validateStatus(ctx context.Context, t *testing.T, profile string) {
	defer PostMortemLogs(t, profile)

	statusOutput := runStatusCmd(ctx, t, profile, false)
	var cs cmd.ClusterState
	if err := json.Unmarshal(statusOutput, &cs); err != nil {
		t.Fatalf("unmarshalling: %v", err)
	}
	// verify the status looks as we expect
	if cs.StatusCode != cmd.Paused {
		t.Fatalf("incorrect status code: %v", cs.StatusCode)
	}
	if cs.StatusName != "Paused" {
		t.Fatalf("incorrect status name: %v", cs.StatusName)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 fuseops

import (
	"reflect"
	"strings"
	"sync"

	"github.com/jacobsa/bazilfuse"
	"github.com/jacobsa/reqtrace"
	"golang.org/x/net/context"
)

// A helper for embedding common behavior.
type commonOp struct {
	opType      string
	r           bazilfuse.Request
	log         func(int, string, ...interface{})
	opsInFlight *sync.WaitGroup

	ctx    context.Context
	report reqtrace.ReportFunc
}

func describeOpType(t reflect.Type) (desc string) {
	name := t.String()

	// The usual case: a string that looks like "*fuseops.GetInodeAttributesOp".
	const prefix = "*fuseops."
	const suffix = "Op"
	if strings.HasPrefix(name, prefix) && strings.HasSuffix(name, suffix) {
		desc = name[len(prefix) : len(name)-len(suffix)]
		return
	}

	// Otherwise, it's not clear what to do.
	desc = t.String()

	return
}

func (o *commonOp) init(
	ctx context.Context,
	opType reflect.Type,
	r bazilfuse.Request,
	log func(int, string, ...interface{}),
	opsInFlight *sync.WaitGroup) {
	// Initialize basic fields.
	o.opType = describeOpType(opType)
	o.r = r
	o.log = log
	o.opsInFlight = opsInFlight

	// Set up a trace span for this op.
	o.ctx, o.report = reqtrace.StartSpan(ctx, o.opType)
}

func (o *commonOp) Header() OpHeader {
	bh := o.r.Hdr()
	return OpHeader{
		Uid: bh.Uid,
		Gid: bh.Gid,
	}
}

func (o *commonOp) Context() context.Context {
	return o.ctx
}

func (o *commonOp) Logf(format string, v ...interface{}) {
	const calldepth = 2
	o.log(calldepth, format, v...)
}

func (o *commonOp) respondErr(err error) {
	if err == nil {
		panic("Expect non-nil here.")
	}

	o.report(err)

	o.Logf(
		"-> (%s) error: %v",
		o.opType,
		err)

	o.r.RespondError(err)
}

// Respond with the supplied response struct, which must be accepted by a
// method called Respond on o.r.
//
// Special case: nil means o.r.Respond accepts no parameters.
func (o *commonOp) respond(resp interface{}) {
	// We were successful.
	o.report(nil)

	// Find the Respond method.
	v := reflect.ValueOf(o.r)
	respond := v.MethodByName("Respond")

	// Special case: handle successful ops with no response struct.
	if resp == nil {
		o.Logf("-> (%s) OK", o.opType)
		respond.Call([]reflect.Value{})
		return
	}

	// Otherwise, pass along the response struct.
	o.Logf("-> %v", resp)
	respond.Call([]reflect.Value{reflect.ValueOf(resp)})
}
<commit_msg>Added a flag for per-PID tracing.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 fuseops

import (
	"flag"
	"reflect"
	"strings"
	"sync"

	"github.com/jacobsa/bazilfuse"
	"github.com/jacobsa/reqtrace"
	"golang.org/x/net/context"
)

var fPerPIDTracing = flag.Bool(
	"fuse.per_pid_tracing",
	false,
	"Enable a hacky mode that uses reqtrace to group all ops from each "+
		"individual PID. Not a good idea to use in production; races, bugs, and "+
		"resource leaks likely lurk.")

// A helper for embedding common behavior.
type commonOp struct {
	opType      string
	r           bazilfuse.Request
	log         func(int, string, ...interface{})
	opsInFlight *sync.WaitGroup

	ctx    context.Context
	report reqtrace.ReportFunc
}

func describeOpType(t reflect.Type) (desc string) {
	name := t.String()

	// The usual case: a string that looks like "*fuseops.GetInodeAttributesOp".
	const prefix = "*fuseops."
	const suffix = "Op"
	if strings.HasPrefix(name, prefix) && strings.HasSuffix(name, suffix) {
		desc = name[len(prefix) : len(name)-len(suffix)]
		return
	}

	// Otherwise, it's not clear what to do.
	desc = t.String()

	return
}

func (o *commonOp) maybeTraceByPID(in context.Context) (out context.Context) {
	// Is there anything to do?
	if !*fPerPIDTracing {
		out = in
		return
	}

	// TODO(jacobsa): Do something interesting.
	out = in
	return
}

func (o *commonOp) init(
	ctx context.Context,
	opType reflect.Type,
	r bazilfuse.Request,
	log func(int, string, ...interface{}),
	opsInFlight *sync.WaitGroup) {
	// Set up a context that reflects per-PID tracing if appropriate.
	ctx = o.maybeTraceByPID(ctx)

	// Initialize basic fields.
	o.opType = describeOpType(opType)
	o.r = r
	o.log = log
	o.opsInFlight = opsInFlight

	// Set up a trace span for this op.
	o.ctx, o.report = reqtrace.StartSpan(ctx, o.opType)
}

func (o *commonOp) Header() OpHeader {
	bh := o.r.Hdr()
	return OpHeader{
		Uid: bh.Uid,
		Gid: bh.Gid,
	}
}

func (o *commonOp) Context() context.Context {
	return o.ctx
}

func (o *commonOp) Logf(format string, v ...interface{}) {
	const calldepth = 2
	o.log(calldepth, format, v...)
}

func (o *commonOp) respondErr(err error) {
	if err == nil {
		panic("Expect non-nil here.")
	}

	o.report(err)

	o.Logf(
		"-> (%s) error: %v",
		o.opType,
		err)

	o.r.RespondError(err)
}

// Respond with the supplied response struct, which must be accepted by a
// method called Respond on o.r.
//
// Special case: nil means o.r.Respond accepts no parameters.
func (o *commonOp) respond(resp interface{}) {
	// We were successful.
	o.report(nil)

	// Find the Respond method.
	v := reflect.ValueOf(o.r)
	respond := v.MethodByName("Respond")

	// Special case: handle successful ops with no response struct.
	if resp == nil {
		o.Logf("-> (%s) OK", o.opType)
		respond.Call([]reflect.Value{})
		return
	}

	// Otherwise, pass along the response struct.
	o.Logf("-> %v", resp)
	respond.Call([]reflect.Value{reflect.ValueOf(resp)})
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"net/url"
	"regexp"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/iam"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsIamRole() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsIamRoleCreate,
		Read:   resourceAwsIamRoleRead,
		Update: resourceAwsIamRoleUpdate,
		Delete: resourceAwsIamRoleDelete,
		Importer: &schema.ResourceImporter{
			State: resourceAwsIamRoleImport,
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"unique_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name_prefix"},
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8329-L8334
					value := v.(string)
					if len(value) > 64 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 64 characters", k))
					}
					if !regexp.MustCompile("^[\\w+=,.@-]*$").MatchString(value) {
						errors = append(errors, fmt.Errorf(
							"%q must match [\\w+=,.@-]", k))
					}
					return
				},
			},

			"name_prefix": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8329-L8334
					value := v.(string)
					if len(value) > 32 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 32 characters, name is limited to 64", k))
					}
					if !regexp.MustCompile("^[\\w+=,.@-]*$").MatchString(value) {
						errors = append(errors, fmt.Errorf(
							"%q must match [\\w+=,.@-]", k))
					}
					return
				},
			},

			"path": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "/",
				ForceNew: true,
			},

			"description": {
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: validateIamRoleDescription,
			},

			"assume_role_policy": {
				Type:             schema.TypeString,
				Required:         true,
				DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
				ValidateFunc:     validateJsonString,
			},

			"force_detach_policies": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"create_date": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsIamRoleImport(
	d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	d.Set("force_detach_policies", false)
	return []*schema.ResourceData{d}, nil
}

func resourceAwsIamRoleCreate(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	var name string
	if v, ok := d.GetOk("name"); ok {
		name = v.(string)
	} else if v, ok := d.GetOk("name_prefix"); ok {
		name = resource.PrefixedUniqueId(v.(string))
	} else {
		name = resource.UniqueId()
	}

	request := &iam.CreateRoleInput{
		Path:                     aws.String(d.Get("path").(string)),
		RoleName:                 aws.String(name),
		AssumeRolePolicyDocument: aws.String(d.Get("assume_role_policy").(string)),
	}

	if v, ok := d.GetOk("description"); ok {
		request.Description = aws.String(v.(string))
	}

	var createResp *iam.CreateRoleOutput
	err := resource.Retry(30*time.Second, func() *resource.RetryError {
		var err error
		createResp, err = iamconn.CreateRole(request)
		// IAM users (referenced in Principal field of assume policy)
		// can take ~30 seconds to propagate in AWS
		if isAWSErr(err, "MalformedPolicyDocument", "Invalid principal in policy") {
			return resource.RetryableError(err)
		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return fmt.Errorf("Error creating IAM Role %s: %s", name, err)
	}
	d.SetId(*createResp.Role.RoleName)
	return resourceAwsIamRoleRead(d, meta)
}

func resourceAwsIamRoleRead(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	request := &iam.GetRoleInput{
		RoleName: aws.String(d.Id()),
	}

	getResp, err := iamconn.GetRole(request)
	if err != nil {
		if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { // XXX test me
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error reading IAM Role %s: %s", d.Id(), err)
	}

	role := getResp.Role

	if err := d.Set("name", role.RoleName); err != nil {
		return err
	}
	if err := d.Set("arn", role.Arn); err != nil {
		return err
	}
	if err := d.Set("path", role.Path); err != nil {
		return err
	}
	if err := d.Set("unique_id", role.RoleId); err != nil {
		return err
	}
	if err := d.Set("create_date", role.CreateDate.Format(time.RFC3339)); err != nil {
		return err
	}

	if role.Description != nil {
		// the description isn't present in the response to CreateRole.
		if err := d.Set("description", role.Description); err != nil {
			return err
		}
	}

	assumRolePolicy, err := url.QueryUnescape(*role.AssumeRolePolicyDocument)
	if err != nil {
		return err
	}
	if err := d.Set("assume_role_policy", assumRolePolicy); err != nil {
		return err
	}
	return nil
}

func resourceAwsIamRoleUpdate(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	if d.HasChange("assume_role_policy") {
		assumeRolePolicyInput := &iam.UpdateAssumeRolePolicyInput{
			RoleName:       aws.String(d.Id()),
			PolicyDocument: aws.String(d.Get("assume_role_policy").(string)),
		}
		_, err := iamconn.UpdateAssumeRolePolicy(assumeRolePolicyInput)
		if err != nil {
			if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
				d.SetId("")
				return nil
			}
			return fmt.Errorf("Error Updating IAM Role (%s) Assume Role Policy: %s", d.Id(), err)
		}
	}

	if d.HasChange("description") {
		roleDescriptionInput := &iam.UpdateRoleDescriptionInput{
			RoleName:    aws.String(d.Id()),
			Description: aws.String(d.Get("description").(string)),
		}
		_, err := iamconn.UpdateRoleDescription(roleDescriptionInput)
		if err != nil {
			if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
				d.SetId("")
				return nil
			}
			return fmt.Errorf("Error Updating IAM Role (%s) Assume Role Policy: %s", d.Id(), err)
		}
	}

	return nil
}

func resourceAwsIamRoleDelete(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	// Roles cannot be destroyed when attached to an existing Instance Profile
	resp, err := iamconn.ListInstanceProfilesForRole(&iam.ListInstanceProfilesForRoleInput{
		RoleName: aws.String(d.Id()),
	})
	if err != nil {
		return fmt.Errorf("Error listing Profiles for IAM Role (%s) when trying to delete: %s", d.Id(), err)
	}

	// Loop and remove this Role from any Profiles
	if len(resp.InstanceProfiles) > 0 {
		for _, i := range resp.InstanceProfiles {
			_, err := iamconn.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{
				InstanceProfileName: i.InstanceProfileName,
				RoleName:            aws.String(d.Id()),
			})
			if err != nil {
				return fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err)
			}
		}
	}

	if d.Get("force_detach_policies").(bool) {
		policiesResp, err := iamconn.ListAttachedRolePolicies(&iam.ListAttachedRolePoliciesInput{
			RoleName: aws.String(d.Id()),
		})
		if err != nil {
			return fmt.Errorf("Error listing Policies for IAM Role (%s) when trying to delete: %s", d.Id(), err)
		}
		// Loop and remove the Policies from the Role
		if len(policiesResp.AttachedPolicies) > 0 {
			for _, i := range policiesResp.AttachedPolicies {
				_, err := iamconn.DetachRolePolicy(&iam.DetachRolePolicyInput{
					PolicyArn: i.PolicyArn,
					RoleName:  aws.String(d.Id()),
				})
				if err != nil {
					return fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err)
				}
			}
		}

		// For inline policies
		rolePolicyNames := make([]*string, 0)
		err = iamconn.ListRolePoliciesPages(&iam.ListRolePoliciesInput{
			RoleName: aws.String(d.Id()),
		}, func(page *iam.ListRolePoliciesOutput, lastPage bool) bool {
			for _, v := range page.PolicyNames {
				rolePolicyNames = append(rolePolicyNames, v)
			}
			return len(page.PolicyNames) > 0
		})
		if err != nil {
			return fmt.Errorf("Error listing inline Policies for IAM Role (%s) when trying to delete: %s", d.Id(), err)
		}
		if len(rolePolicyNames) > 0 {
			for _, pname := range rolePolicyNames {
				_, err := iamconn.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
					PolicyName: pname,
					RoleName:   aws.String(d.Id()),
				})
				if err != nil {
					return fmt.Errorf("Error deleting inline policy of IAM Role %s: %s", d.Id(), err)
				}
			}
		}
	}

	request := &iam.DeleteRoleInput{
		RoleName: aws.String(d.Id()),
	}

	// IAM is eventually consistent and deletion of attached policies may take time
	return resource.Retry(30*time.Second, func() *resource.RetryError {
		_, err := iamconn.DeleteRole(request)
		if err != nil {
			awsErr, ok := err.(awserr.Error)
			if ok && awsErr.Code() == "DeleteConflict" {
				return resource.RetryableError(err)
			}

			return resource.NonRetryableError(fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err))
		}
		return nil
	})
}
<commit_msg>Use ListAttachedRolePoliciesPages<commit_after>package aws

import (
	"fmt"
	"net/url"
	"regexp"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/iam"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsIamRole() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsIamRoleCreate,
		Read:   resourceAwsIamRoleRead,
		Update: resourceAwsIamRoleUpdate,
		Delete: resourceAwsIamRoleDelete,
		Importer: &schema.ResourceImporter{
			State: resourceAwsIamRoleImport,
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"unique_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name_prefix"},
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8329-L8334
					value := v.(string)
					if len(value) > 64 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 64 characters", k))
					}
					if !regexp.MustCompile("^[\\w+=,.@-]*$").MatchString(value) {
						errors = append(errors, fmt.Errorf(
							"%q must match [\\w+=,.@-]", k))
					}
					return
				},
			},

			"name_prefix": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8329-L8334
					value := v.(string)
					if len(value) > 32 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 32 characters, name is limited to 64", k))
					}
					if !regexp.MustCompile("^[\\w+=,.@-]*$").MatchString(value) {
						errors = append(errors, fmt.Errorf(
							"%q must match [\\w+=,.@-]", k))
					}
					return
				},
			},

			"path": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "/",
				ForceNew: true,
			},

			"description": {
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: validateIamRoleDescription,
			},

			"assume_role_policy": {
				Type:             schema.TypeString,
				Required:         true,
				DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
				ValidateFunc:     validateJsonString,
			},

			"force_detach_policies": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"create_date": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsIamRoleImport(
	d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	d.Set("force_detach_policies", false)
	return []*schema.ResourceData{d}, nil
}

func resourceAwsIamRoleCreate(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	var name string
	if v, ok := d.GetOk("name"); ok {
		name = v.(string)
	} else if v, ok := d.GetOk("name_prefix"); ok {
		name = resource.PrefixedUniqueId(v.(string))
	} else {
		name = resource.UniqueId()
	}

	request := &iam.CreateRoleInput{
		Path:                     aws.String(d.Get("path").(string)),
		RoleName:                 aws.String(name),
		AssumeRolePolicyDocument: aws.String(d.Get("assume_role_policy").(string)),
	}

	if v, ok := d.GetOk("description"); ok {
		request.Description = aws.String(v.(string))
	}

	var createResp *iam.CreateRoleOutput
	err := resource.Retry(30*time.Second, func() *resource.RetryError {
		var err error
		createResp, err = iamconn.CreateRole(request)
		// IAM users (referenced in Principal field of assume policy)
		// can take ~30 seconds to propagate in AWS
		if isAWSErr(err, "MalformedPolicyDocument", "Invalid principal in policy") {
			return resource.RetryableError(err)
		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return fmt.Errorf("Error creating IAM Role %s: %s", name, err)
	}
	d.SetId(*createResp.Role.RoleName)
	return resourceAwsIamRoleRead(d, meta)
}

func resourceAwsIamRoleRead(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	request := &iam.GetRoleInput{
		RoleName: aws.String(d.Id()),
	}

	getResp, err := iamconn.GetRole(request)
	if err != nil {
		if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { // XXX test me
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error reading IAM Role %s: %s", d.Id(), err)
	}

	role := getResp.Role

	if err := d.Set("name", role.RoleName); err != nil {
		return err
	}
	if err := d.Set("arn", role.Arn); err != nil {
		return err
	}
	if err := d.Set("path", role.Path); err != nil {
		return err
	}
	if err := d.Set("unique_id", role.RoleId); err != nil {
		return err
	}
	if err := d.Set("create_date", role.CreateDate.Format(time.RFC3339)); err != nil {
		return err
	}

	if role.Description != nil {
		// the description isn't present in the response to CreateRole.
		if err := d.Set("description", role.Description); err != nil {
			return err
		}
	}

	assumRolePolicy, err := url.QueryUnescape(*role.AssumeRolePolicyDocument)
	if err != nil {
		return err
	}
	if err := d.Set("assume_role_policy", assumRolePolicy); err != nil {
		return err
	}
	return nil
}

func resourceAwsIamRoleUpdate(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	if d.HasChange("assume_role_policy") {
		assumeRolePolicyInput := &iam.UpdateAssumeRolePolicyInput{
			RoleName:       aws.String(d.Id()),
			PolicyDocument: aws.String(d.Get("assume_role_policy").(string)),
		}
		_, err := iamconn.UpdateAssumeRolePolicy(assumeRolePolicyInput)
		if err != nil {
			if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
				d.SetId("")
				return nil
			}
			return fmt.Errorf("Error Updating IAM Role (%s) Assume Role Policy: %s", d.Id(), err)
		}
	}

	if d.HasChange("description") {
		roleDescriptionInput := &iam.UpdateRoleDescriptionInput{
			RoleName:    aws.String(d.Id()),
			Description: aws.String(d.Get("description").(string)),
		}
		_, err := iamconn.UpdateRoleDescription(roleDescriptionInput)
		if err != nil {
			if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
				d.SetId("")
				return nil
			}
			return fmt.Errorf("Error Updating IAM Role (%s) Assume Role Policy: %s", d.Id(), err)
		}
	}

	return nil
}

func resourceAwsIamRoleDelete(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	// Roles cannot be destroyed when attached to an existing Instance Profile
	resp, err := iamconn.ListInstanceProfilesForRole(&iam.ListInstanceProfilesForRoleInput{
		RoleName: aws.String(d.Id()),
	})
	if err != nil {
		return fmt.Errorf("Error listing Profiles for IAM Role (%s) when trying to delete: %s", d.Id(), err)
	}

	// Loop and remove this Role from any Profiles
	if len(resp.InstanceProfiles) > 0 {
		for _, i := range resp.InstanceProfiles {
			_, err := iamconn.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{
				InstanceProfileName: i.InstanceProfileName,
				RoleName:            aws.String(d.Id()),
			})
			if err != nil {
				return fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err)
			}
		}
	}

	if d.Get("force_detach_policies").(bool) {
		// For managed policies
		managedPolicies := make([]*string, 0)
		err = iamconn.ListAttachedRolePoliciesPages(&iam.ListAttachedRolePoliciesInput{
			RoleName: aws.String(d.Id()),
		}, func(page *iam.ListAttachedRolePoliciesOutput, lastPage bool) bool {
			for _, v := range page.AttachedPolicies {
				managedPolicies = append(managedPolicies, v.PolicyArn)
			}
			return len(page.AttachedPolicies) > 0
		})
		if err != nil {
			return fmt.Errorf("Error listing Policies for IAM Role (%s) when trying to delete: %s", d.Id(), err)
		}
		if len(managedPolicies) > 0 {
			for _, parn := range managedPolicies {
				_, err = iamconn.DetachRolePolicy(&iam.DetachRolePolicyInput{
					PolicyArn: parn,
					RoleName:  aws.String(d.Id()),
				})
				if err != nil {
					return fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err)
				}
			}
		}

		// For inline policies
		inlinePolicies := make([]*string, 0)
		err = iamconn.ListRolePoliciesPages(&iam.ListRolePoliciesInput{
			RoleName: aws.String(d.Id()),
		}, func(page *iam.ListRolePoliciesOutput, lastPage bool) bool {
			for _, v := range page.PolicyNames {
				inlinePolicies = append(inlinePolicies, v)
			}
			return len(page.PolicyNames) > 0
		})
		if err != nil {
			return fmt.Errorf("Error listing inline Policies for IAM Role (%s) when trying to delete: %s", d.Id(), err)
		}
		if len(inlinePolicies) > 0 {
			for _, pname := range inlinePolicies {
				_, err := iamconn.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
					PolicyName: pname,
					RoleName:   aws.String(d.Id()),
				})
				if err != nil {
					return fmt.Errorf("Error deleting inline policy of IAM Role %s: %s", d.Id(), err)
				}
			}
		}
	}

	request := &iam.DeleteRoleInput{
		RoleName: aws.String(d.Id()),
	}

	// IAM is eventually consistent and deletion of attached policies may take time
	return resource.Retry(30*time.Second, func() *resource.RetryError {
		_, err := iamconn.DeleteRole(request)
		if err != nil {
			awsErr, ok := err.(awserr.Error)
			if ok && awsErr.Code() == "DeleteConflict" {
				return resource.RetryableError(err)
			}

			return resource.NonRetryableError(fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err))
		}
		return nil
	})
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2019 Tigera, Inc. All rights reserved.
//
// 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 proxy

import (
	"net"
	"sync"

	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"
	"k8s.io/client-go/kubernetes"

	"github.com/projectcalico/felix/bpf"
)

// KubeProxy is a wrapper of Proxy that deals with higher level issue like
// configuration, restarting etc.
type KubeProxy struct {
	proxy Proxy

	hostIPUpdates chan []net.IP
	stopOnce      sync.Once
	lock          sync.Mutex
	exiting       chan struct{}
	wg            sync.WaitGroup

	k8s         kubernetes.Interface
	hostname    string
	frontendMap bpf.Map
	backendMap  bpf.Map
	opts        []Option
}

// StartKubeProxy start a new kube-proxy if there was no error
func StartKubeProxy(k8s kubernetes.Interface, hostname string,
	frontendMap, backendMap bpf.Map, opts ...Option) (*KubeProxy, error) {

	kp := &KubeProxy{
		k8s:         k8s,
		hostname:    hostname,
		frontendMap: frontendMap,
		backendMap:  backendMap,
		opts:        opts,

		hostIPUpdates: make(chan []net.IP, 1),
		exiting:       make(chan struct{}),
	}

	go func() {
		err := kp.start()
		if err != nil {
			log.Panic("kube-proxy failed to start")
		}
	}()

	return kp, nil
}

// Stop stops KubeProxy and waits for it to exit
func (kp *KubeProxy) Stop() {
	kp.stopOnce.Do(func() {
		kp.lock.Lock()
		defer kp.lock.Unlock()

		close(kp.exiting)
		close(kp.hostIPUpdates)
		kp.proxy.Stop()
		kp.wg.Wait()
	})
}

func (kp *KubeProxy) run(hostIPs []net.IP) error {

	kp.lock.Lock()
	defer kp.lock.Unlock()

	syncer, err := NewSyncer(hostIPs, kp.frontendMap, kp.backendMap)
	if err != nil {
		return errors.WithMessage(err, "new bpf syncer")
	}

	proxy, err := New(kp.k8s, syncer, kp.hostname, kp.opts...)
	if err != nil {
		return errors.WithMessage(err, "new proxy")
	}

	log.Infof("kube-proxy started, hostname=%q hostIPs=%+v", kp.hostname, hostIPs)

	kp.proxy = proxy

	return nil
}

func (kp *KubeProxy) start() error {

	// wait for the initial update
	hostIPs := <-kp.hostIPUpdates

	err := kp.run(hostIPs)
	if err != nil {
		return err
	}

	kp.wg.Add(1)
	go func() {
		defer kp.wg.Done()
		for {
			hostIPs, ok := <-kp.hostIPUpdates
			if !ok {
				defer log.Error("kube-proxy stopped since hostIPUpdates closed")
				kp.proxy.Stop()
				return
			}

			stopped := make(chan struct{})

			go func() {
				defer close(stopped)
				defer log.Info("kube-proxy stopped to restart with updated host IPs")
				kp.proxy.Stop()
			}()

		waitforstop:
			for {
				select {
				case hostIPs, ok = <-kp.hostIPUpdates:
					if !ok {
						log.Error("kube-proxy: hostIPUpdates closed")
						return
					}
				case <-kp.exiting:
					log.Info("kube-proxy: exiting")
					return
				case <-stopped:
					err = kp.run(hostIPs)
					if err != nil {
						log.Panic("kube-proxy failed to start after host IPs update")
					}
					break waitforstop
				}
			}
		}
	}()

	return nil
}

// OnHostIPsUpdate should be used by an external user to update the proxy's list
// of host IPs
func (kp *KubeProxy) OnHostIPsUpdate(IPs []net.IP) {
	select {
	case kp.hostIPUpdates <- IPs:
		// nothing
	default:
		// in case we would block, drop the no stale update and replace it
		// with a new one. Do it non-blocking way in case it was just consumed.
		select {
		case <-kp.hostIPUpdates:
		default:
		}
		kp.hostIPUpdates <- IPs
	}
	log.Debugf("kube-proxy OnHostIPsUpdate: %+v", IPs)
}
<commit_msg>bpf kube-proxy fix typo<commit_after>// Copyright (c) 2017-2019 Tigera, Inc. All rights reserved.
//
// 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 proxy

import (
	"net"
	"sync"

	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"
	"k8s.io/client-go/kubernetes"

	"github.com/projectcalico/felix/bpf"
)

// KubeProxy is a wrapper of Proxy that deals with higher level issue like
// configuration, restarting etc.
type KubeProxy struct {
	proxy Proxy

	hostIPUpdates chan []net.IP
	stopOnce      sync.Once
	lock          sync.Mutex
	exiting       chan struct{}
	wg            sync.WaitGroup

	k8s         kubernetes.Interface
	hostname    string
	frontendMap bpf.Map
	backendMap  bpf.Map
	opts        []Option
}

// StartKubeProxy start a new kube-proxy if there was no error
func StartKubeProxy(k8s kubernetes.Interface, hostname string,
	frontendMap, backendMap bpf.Map, opts ...Option) (*KubeProxy, error) {

	kp := &KubeProxy{
		k8s:         k8s,
		hostname:    hostname,
		frontendMap: frontendMap,
		backendMap:  backendMap,
		opts:        opts,

		hostIPUpdates: make(chan []net.IP, 1),
		exiting:       make(chan struct{}),
	}

	go func() {
		err := kp.start()
		if err != nil {
			log.Panic("kube-proxy failed to start")
		}
	}()

	return kp, nil
}

// Stop stops KubeProxy and waits for it to exit
func (kp *KubeProxy) Stop() {
	kp.stopOnce.Do(func() {
		kp.lock.Lock()
		defer kp.lock.Unlock()

		close(kp.exiting)
		close(kp.hostIPUpdates)
		kp.proxy.Stop()
		kp.wg.Wait()
	})
}

func (kp *KubeProxy) run(hostIPs []net.IP) error {

	kp.lock.Lock()
	defer kp.lock.Unlock()

	syncer, err := NewSyncer(hostIPs, kp.frontendMap, kp.backendMap)
	if err != nil {
		return errors.WithMessage(err, "new bpf syncer")
	}

	proxy, err := New(kp.k8s, syncer, kp.hostname, kp.opts...)
	if err != nil {
		return errors.WithMessage(err, "new proxy")
	}

	log.Infof("kube-proxy started, hostname=%q hostIPs=%+v", kp.hostname, hostIPs)

	kp.proxy = proxy

	return nil
}

func (kp *KubeProxy) start() error {

	// wait for the initial update
	hostIPs := <-kp.hostIPUpdates

	err := kp.run(hostIPs)
	if err != nil {
		return err
	}

	kp.wg.Add(1)
	go func() {
		defer kp.wg.Done()
		for {
			hostIPs, ok := <-kp.hostIPUpdates
			if !ok {
				defer log.Error("kube-proxy stopped since hostIPUpdates closed")
				kp.proxy.Stop()
				return
			}

			stopped := make(chan struct{})

			go func() {
				defer close(stopped)
				defer log.Info("kube-proxy stopped to restart with updated host IPs")
				kp.proxy.Stop()
			}()

		waitforstop:
			for {
				select {
				case hostIPs, ok = <-kp.hostIPUpdates:
					if !ok {
						log.Error("kube-proxy: hostIPUpdates closed")
						return
					}
				case <-kp.exiting:
					log.Info("kube-proxy: exiting")
					return
				case <-stopped:
					err = kp.run(hostIPs)
					if err != nil {
						log.Panic("kube-proxy failed to start after host IPs update")
					}
					break waitforstop
				}
			}
		}
	}()

	return nil
}

// OnHostIPsUpdate should be used by an external user to update the proxy's list
// of host IPs
func (kp *KubeProxy) OnHostIPsUpdate(IPs []net.IP) {
	select {
	case kp.hostIPUpdates <- IPs:
		// nothing
	default:
		// in case we would block, drop the now stale update and replace it
		// with a new one. Do it non-blocking way in case it was just consumed.
		select {
		case <-kp.hostIPUpdates:
		default:
		}
		kp.hostIPUpdates <- IPs
	}
	log.Debugf("kube-proxy OnHostIPsUpdate: %+v", IPs)
}
<|endoftext|>


<commit_before>package util

var l = NewLog("mpeg:util")

func NewBinaryTreeHuffmanDecoder(init HuffmanTable) HuffmanDecoder {
	root, depth := parseInitIntoTree(init)
	return &binaryTreeHuffmanDecoder{root, depth}
}

type binaryTreeHuffmanDecoder struct {
	root  *binaryHuffmanNode
	depth uint
}

type binaryHuffmanNode struct {
	left  interface{}
	right interface{}
}

func parseInitIntoTree(init HuffmanTable) (*binaryHuffmanNode, uint) {
	root := &binaryHuffmanNode{}
	var depth uint = 0

	for _, value := range init {
		currentNode := root

		bitStringLength := len(value.BitString)
		if uint(bitStringLength) > depth {
			depth = uint(bitStringLength)
		}

		for i := 0; i < bitStringLength; i++ {

			bit := value.BitString[i : i+1]

			if i < bitStringLength-1 {
				// Descending
				if bit == "1" {
					if currentNode.left == nil {
						nextNode := &binaryHuffmanNode{}
						currentNode.left = nextNode
						currentNode = nextNode
					} else if nextNode, ok := currentNode.left.(*binaryHuffmanNode); ok {
						currentNode = nextNode
					} else {
						panic("Invalid huffman tree")
					}
				} else {
					if currentNode.right == nil {
						nextNode := &binaryHuffmanNode{}
						currentNode.right = nextNode
						currentNode = nextNode
					} else if nextNode, ok := currentNode.right.(*binaryHuffmanNode); ok {
						currentNode = nextNode
					} else {
						panic("Invalid huffman tree")
					}
				}
			} else {
				// Ending

				if bit == "1" {
					currentNode.left = value.Value
				} else {
					currentNode.right = value.Value
				}
			}
		}
	}

	return root, depth
}

func (self *binaryTreeHuffmanDecoder) Decode(br BitReader32) (interface{}, error) {

	nextbits, err := br.Peek32(self.depth)

	if err != nil {
		return nil, err
	}

	currentNode := self.root

	for i := uint(1); i <= self.depth; i++ {
		var val interface{}

		mask := uint32(1) << (self.depth - i)
		bit := nextbits&mask == mask

		l.Printf("%b %b %t\n", nextbits, mask, bit)

		if bit {
			val = currentNode.left
		} else {
			val = currentNode.right
		}

		if nextNode, ok := val.(*binaryHuffmanNode); ok {
			currentNode = nextNode
		} else {
			br.Trash(i)
			return val, nil
		}
	}

	return nil, ErrMissingHuffmanValue
}
<commit_msg>whoops. logging stuff!<commit_after>package util

func NewBinaryTreeHuffmanDecoder(init HuffmanTable) HuffmanDecoder {
	root, depth := parseInitIntoTree(init)
	return &binaryTreeHuffmanDecoder{root, depth}
}

type binaryTreeHuffmanDecoder struct {
	root  *binaryHuffmanNode
	depth uint
}

type binaryHuffmanNode struct {
	left  interface{}
	right interface{}
}

func parseInitIntoTree(init HuffmanTable) (*binaryHuffmanNode, uint) {
	root := &binaryHuffmanNode{}
	var depth uint = 0

	for _, value := range init {
		currentNode := root

		bitStringLength := len(value.BitString)
		if uint(bitStringLength) > depth {
			depth = uint(bitStringLength)
		}

		for i := 0; i < bitStringLength; i++ {

			bit := value.BitString[i : i+1]

			if i < bitStringLength-1 {
				// Descending
				if bit == "1" {
					if currentNode.left == nil {
						nextNode := &binaryHuffmanNode{}
						currentNode.left = nextNode
						currentNode = nextNode
					} else if nextNode, ok := currentNode.left.(*binaryHuffmanNode); ok {
						currentNode = nextNode
					} else {
						panic("Invalid huffman tree")
					}
				} else {
					if currentNode.right == nil {
						nextNode := &binaryHuffmanNode{}
						currentNode.right = nextNode
						currentNode = nextNode
					} else if nextNode, ok := currentNode.right.(*binaryHuffmanNode); ok {
						currentNode = nextNode
					} else {
						panic("Invalid huffman tree")
					}
				}
			} else {
				// Ending

				if bit == "1" {
					currentNode.left = value.Value
				} else {
					currentNode.right = value.Value
				}
			}
		}
	}

	return root, depth
}

func (self *binaryTreeHuffmanDecoder) Decode(br BitReader32) (interface{}, error) {

	nextbits, err := br.Peek32(self.depth)

	if err != nil {
		return nil, err
	}

	currentNode := self.root

	for i := uint(1); i <= self.depth; i++ {
		var val interface{}

		mask := uint32(1) << (self.depth - i)
		bit := nextbits&mask == mask

		if bit {
			val = currentNode.left
		} else {
			val = currentNode.right
		}

		if nextNode, ok := val.(*binaryHuffmanNode); ok {
			currentNode = nextNode
		} else {
			br.Trash(i)
			return val, nil
		}
	}

	return nil, ErrMissingHuffmanValue
}
<|endoftext|>


<commit_before>package common

import (
  "testing"
  "bytes"

	"github.com/blockfreight/blockfreight-alpha/lib/pkg/common"
)

func TestHashByteArrays(t* testing.T){
  t.Log("Test HashBytesArrays on Common Lib")
  first_hash := []byte("firstHash")
  second_hash := []byte("secondHash")
  result_expected := []byte{35, 63, 72, 164, 129, 98, 5, 123, 77, 35, 41, 21, 136, 230, 199, 208, 195, 68, 188, 65, 198, 199, 175, 43, 113, 168, 46, 95, 93, 208, 85, 227}

  resultCommon := common.HashByteArrays(first_hash, second_hash)

  if  bytes.Compare(resultCommon, result_expected) != 0 {
    t.Error("Error on HashByteArrays!")
  }
}
<commit_msg>Fixing gofmt issue<commit_after>package common

import (
	"bytes"
	"testing"

	"github.com/blockfreight/blockfreight-alpha/lib/pkg/common"
)

func TestHashByteArrays(t *testing.T) {
	t.Log("Test HashBytesArrays on Common Lib")
	first_hash := []byte("firstHash")
	second_hash := []byte("secondHash")
	result_expected := []byte{35, 63, 72, 164, 129, 98, 5, 123, 77, 35, 41, 21, 136, 230, 199, 208, 195, 68, 188, 65, 198, 199, 175, 43, 113, 168, 46, 95, 93, 208, 85, 227}

	resultCommon := common.HashByteArrays(first_hash, second_hash)

	if bytes.Compare(resultCommon, result_expected) != 0 {
		t.Error("Error on HashByteArrays!")
	}
}
<|endoftext|>


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

package main

import (
	"bytes"
	"fmt"
	"net/http"
	"net/url"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/googleapi"
	"google.golang.org/api/storage/v1"

	"v.io/x/devtools/internal/collect"
	"v.io/x/devtools/internal/tool"
	"v.io/x/lib/cmdline"
)

var (
	colorFlag   bool
	dryRunFlag  bool
	verboseFlag bool

	datePrefixFlag string
	keyFileFlag    string
	outputDirFlag  string
)

const (
	binariesBucketName = "vanadium-binaries"
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	cmdRoot.Flags.BoolVar(&verboseFlag, "v", false, "Print verbose output.")
	cmdRoot.Flags.BoolVar(&dryRunFlag, "n", false, "Show what commands will run but do not execute them.")
	cmdRoot.Flags.BoolVar(&colorFlag, "color", true, "Use color to format output.")

	cmdRoot.Flags.StringVar(&keyFileFlag, "key-file", "", "Google Developers service account JSON key file.")
	cmdRoot.Flags.StringVar(&datePrefixFlag, "date-prefix", "", "Date prefix to match daily build timestamps. Must be a prefix of YYYY-MM-DD.")
	cmdDownload.Flags.StringVar(&outputDirFlag, "output-dir", "", "Directory for storing downloaded binaries.")
}

// root returns a command that represents the root of the vbinary tool.
func root() *cmdline.Command {
	return cmdRoot
}

// cmdRoot represents the "vbinary" command.
var cmdRoot = &cmdline.Command{
	Name:  "vbinary",
	Short: "Access daily builds of Vanadium binaries",
	Long: `
Daily builds of Vanadium binaries are stored in a Google Storage
bucket. This command facilitates retrieval of these binaries, for
instance for the purpose of regression testing.
`,
	Children: []*cmdline.Command{cmdList, cmdDownload},
}

// cmdList represents the "vbinary list" command.
var cmdList = &cmdline.Command{
	Run:   runList,
	Name:  "list",
	Short: "List existing daily builds of Vanadium binaries",
	Long: `
List existing daily builds of Vanadium binaries. The displayed dates can be
limited with the --date-prefix flag.
`,
}

func runList(command *cmdline.Command, _ []string) error {
	ctx := tool.NewContextFromCommand(command, tool.ContextOpts{
		Color:   &colorFlag,
		DryRun:  &dryRunFlag,
		Verbose: &verboseFlag,
	})
	client, err := createClient(ctx)
	if err != nil {
		return err
	}
	service, err := storage.New(client)
	if err != nil {
		return err
	}
	binaries, err := binarySnapshots(service)
	if err != nil {
		return err
	}
	for _, name := range binaries {
		fmt.Fprintf(ctx.Stdout(), "%s\n", name)
	}
	return nil
}

// cmdDownload represents the "vbinary download" command.
var cmdDownload = &cmdline.Command{
	Run:   runDownload,
	Name:  "download",
	Short: "Download an existing daily build of Vanadium binaries",
	Long: `
Download an existing daily build of Vanadium binaries. The latest snapshot within
the --date-prefix range will be downloaded. If no --date-prefix flag is provided,
the overall latest snapshot will be downloaded.`,
}

func runDownload(command *cmdline.Command, args []string) error {
	ctx := tool.NewContextFromCommand(command, tool.ContextOpts{
		Color:   &colorFlag,
		DryRun:  &dryRunFlag,
		Verbose: &verboseFlag,
	})
	client, err := createClient(ctx)
	if err != nil {
		return err
	}

	binaries, timestamp, err := latestBinaries(client)
	if err != nil {
		return err
	}
	if len(outputDirFlag) == 0 {
		outputDirFlag = fmt.Sprintf("./v23_%s_%s_%s", runtime.GOOS, runtime.GOARCH, timestamp)
	}
	if err := ctx.Run().MkdirAll(outputDirFlag, 0755); err != nil {
		return fmt.Errorf("Error while creating directory %s: %s", outputDirFlag, err)
	}

	numBinaries := len(binaries)
	downloadBinaries := func() error {
		errChan := make(chan error, numBinaries)
		for _, name := range binaries {
			go downloadBinary(ctx, client, name, errChan)
		}
		gotError := false
		for i := 0; i < numBinaries; i++ {
			if err := <-errChan; err != nil {
				fmt.Fprintf(ctx.Stderr(), "failed to download binary: %v", err)
				gotError = true
			}
		}
		if gotError {
			if err := ctx.Run().RemoveAll(outputDirFlag); err != nil {
				fmt.Fprintf(ctx.Stderr(), "failed to remove %s: %v", outputDirFlag, err)
			}
			return fmt.Errorf("operation failed")
		}
		return nil
	}
	return ctx.Run().Function(downloadBinaries, fmt.Sprintf("Downloading binaries to %s", outputDirFlag))
}

// latestBinaries returns the binaries of the latest snapshot whose timestamp
// matches the datePrefixFlag, along with the matching timestamp.
func latestBinaries(client *http.Client) ([]string, string, error) {
	service, err := storage.New(client)
	if err != nil {
		return nil, "", err
	}
	timestamp, err := latestTimestamp(client, service)
	if err != nil {
		return nil, "", err
	}
	binaryPrefix := fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, timestamp)
	res, err := service.Objects.List(binariesBucketName).Fields("nextPageToken", "items/name").Prefix(binaryPrefix).Do()
	if err != nil {
		return nil, "", err
	}
	objs := res.Items
	for res.NextPageToken != "" {
		res, err = service.Objects.List(binariesBucketName).PageToken(res.NextPageToken).Do()
		if err != nil {
			return nil, "", err
		}
		objs = append(objs, res.Items...)
	}
	if len(objs) == 0 {
		return nil, "", fmt.Errorf("no binaries found (OS: %s, Arch: %s, Date: %s)", runtime.GOOS, runtime.GOARCH, timestamp)
	}
	ret := make([]string, len(objs))
	for i, obj := range objs {
		ret[i] = obj.Name
	}
	return ret, timestamp, nil
}

// latestTimestamp returns the time the latest snapshot within the
// date-prefix range.
func latestTimestamp(client *http.Client, service *storage.Service) (string, error) {
	// If no datePrefixFlag is provided, we just want to get the latest snapshot.
	if datePrefixFlag == "" {
		latestFile := fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, "latest")
		b, err := downloadFileBytes(client, latestFile)
		if err != nil {
			return "", err
		}
		return string(b), nil
	}
	// Otherwise, we get the snapshots that match datePrefixFlag and choose the latest.
	snapshots, err := binarySnapshots(service)
	if err != nil {
		return "", err
	}
	const layout = "2006-01-02T15:04:05-07:00"
	var latest string
	var latestTime time.Time
	for _, name := range snapshots {
		spl := strings.Split(name, "/")
		timestamp := spl[1]
		t, err := time.Parse(layout, timestamp)
		if err != nil {
			return "", err
		}
		if t.After(latestTime) {
			latest = timestamp
			latestTime = t
		}
	}
	if latest == "" {
		return "", fmt.Errorf("no binaries exist")
	}
	return latest, nil
}

func binarySnapshots(service *storage.Service) ([]string, error) {
	// TODO(suharshs,jsimsa): Snapshots have a .done file written to them if they
	// were completely successful. We need to have this code only display the snapshot
	// if the .done file is present.
	binaryPrefix := fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, datePrefixFlag)
	// We delimit results by the end of the timestamp string so that we don't display
	// duplicate timestamps for each binary.
	res, err := service.Objects.List(binariesBucketName).Fields("nextPageToken", "prefixes").Prefix(binaryPrefix).Delimiter(":00/").Do()
	if err != nil {
		return nil, err
	}
	snapshots := res.Prefixes
	for res.NextPageToken != "" {
		res, err = service.Objects.List(binariesBucketName).PageToken(res.NextPageToken).Do()
		if err != nil {
			return nil, err
		}
		snapshots = append(snapshots, res.Prefixes...)
	}
	if len(snapshots) == 0 {
		return nil, fmt.Errorf("no snapshots found (OS: %s, Arch: %s, Date: %s)", runtime.GOOS, runtime.GOARCH, datePrefixFlag)
	}
	return snapshots, nil
}

func createClient(ctx *tool.Context) (*http.Client, error) {
	oauthHttpClient := &http.Client{}
	if len(keyFileFlag) > 0 {
		data, err := ctx.Run().ReadFile(keyFileFlag)
		if err != nil {
			return nil, err
		}
		conf, err := google.JWTConfigFromJSON(data, storage.CloudPlatformScope)
		if err != nil {
			return nil, fmt.Errorf("failed to create JWT config file: %v", err)
		}
		oauthHttpClient = conf.Client(oauth2.NoContext)
	}
	return oauthHttpClient, nil
}

func downloadBinary(ctx *tool.Context, client *http.Client, binaryPath string, errChan chan<- error) {
	helper := func() error {
		b, err := downloadFileBytes(client, binaryPath)
		if err != nil {
			return fmt.Errorf("failed to download file %v: %v", binaryPath, err)
		}
		fileName := filepath.Join(outputDirFlag, path.Base(binaryPath))
		if err := ctx.Run().WriteFile(fileName, b, 0755); err != nil {
			return fmt.Errorf("failed to write file: %v", err)
		}
		return nil
	}
	errChan <- helper()
}

func downloadFileBytes(client *http.Client, filePath string) (b []byte, e error) {
	// This roundabout request is required because of the issue detailed here:
	// https://plus.sandbox.google.com/+IanRose/posts/Tzw3QZqEQZk
	// and here:
	// https://groups.google.com/forum/#!msg/Golang-nuts/juguXl-ss2Q/oOVFvHYqoSgJ.
	urls := "https://www.googleapis.com/download/storage/v1/b/{bucket}/o/{object}?alt=media"
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request to %s: %v\n", urls, err)
	}
	req.URL.Path = strings.Replace(req.URL.Path, "{bucket}", url.QueryEscape(binariesBucketName), 1)
	req.URL.Path = strings.Replace(req.URL.Path, "{object}", url.QueryEscape(filePath), 1)
	googleapi.SetOpaque(req.URL)
	res, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to download %v: %v\n", req.URL.RequestURI(), err)
	}
	if res.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("got StatusCode %v for download %v", req.URL.RequestURI(), res.StatusCode)
	}
	defer collect.Error(func() error { return res.Body.Close() }, &e)

	var buf bytes.Buffer
	if _, err := buf.ReadFrom(res.Body); err != nil {
		return nil, fmt.Errorf("failed to read response body: %v", err)
	}
	return buf.Bytes(), nil
}
<commit_msg>devtools/vbinary: Check that snapshots were completed before listing of downloading them.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"fmt"
	"net/http"
	"net/url"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/googleapi"
	"google.golang.org/api/storage/v1"

	"v.io/x/devtools/internal/collect"
	"v.io/x/devtools/internal/tool"
	"v.io/x/lib/cmdline"
)

var (
	colorFlag   bool
	dryRunFlag  bool
	verboseFlag bool

	datePrefixFlag string
	keyFileFlag    string
	outputDirFlag  string
)

const (
	binariesBucketName = "vanadium-binaries"

	// NoValidSnapshotsExitCode is returned when there are no valid snapshots for the --date-prefix specified.
	NoValidSnapshotsExitCode = 3
)

// TODO(suharshs): Add tests that mock out google.Storage.

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	cmdRoot.Flags.BoolVar(&verboseFlag, "v", false, "Print verbose output.")
	cmdRoot.Flags.BoolVar(&dryRunFlag, "n", false, "Show what commands will run but do not execute them.")
	cmdRoot.Flags.BoolVar(&colorFlag, "color", true, "Use color to format output.")

	cmdRoot.Flags.StringVar(&keyFileFlag, "key-file", "", "Google Developers service account JSON key file.")
	cmdRoot.Flags.StringVar(&datePrefixFlag, "date-prefix", "", "Date prefix to match daily build timestamps. Must be a prefix of YYYY-MM-DD.")
	cmdDownload.Flags.StringVar(&outputDirFlag, "output-dir", "", "Directory for storing downloaded binaries.")
}

// root returns a command that represents the root of the vbinary tool.
func root() *cmdline.Command {
	return cmdRoot
}

// cmdRoot represents the "vbinary" command.
var cmdRoot = &cmdline.Command{
	Name:  "vbinary",
	Short: "Access daily builds of Vanadium binaries",
	Long: `
Daily builds of Vanadium binaries are stored in a Google Storage
bucket. This command facilitates retrieval of these binaries, for
instance for the purpose of regression testing.
`,
	Children: []*cmdline.Command{cmdList, cmdDownload},
}

// cmdList represents the "vbinary list" command.
var cmdList = &cmdline.Command{
	Run:   runList,
	Name:  "list",
	Short: "List existing daily builds of Vanadium binaries",
	Long: `
List existing daily builds of Vanadium binaries. The displayed dates can be
limited with the --date-prefix flag.
`,
}

func runList(command *cmdline.Command, _ []string) error {
	ctx := tool.NewContextFromCommand(command, tool.ContextOpts{
		Color:   &colorFlag,
		DryRun:  &dryRunFlag,
		Verbose: &verboseFlag,
	})
	client, err := createClient(ctx)
	if err != nil {
		return err
	}
	service, err := storage.New(client)
	if err != nil {
		return err
	}
	binaries, err := binarySnapshots(ctx, service)
	if err != nil {
		return err
	}
	for _, name := range binaries {
		fmt.Fprintf(ctx.Stdout(), "%s\n", name)
	}
	return nil
}

// cmdDownload represents the "vbinary download" command.
var cmdDownload = &cmdline.Command{
	Run:   runDownload,
	Name:  "download",
	Short: "Download an existing daily build of Vanadium binaries",
	Long: `
Download an existing daily build of Vanadium binaries. The latest snapshot within
the --date-prefix range will be downloaded. If no --date-prefix flag is provided,
the overall latest snapshot will be downloaded.`,
}

func runDownload(command *cmdline.Command, args []string) error {
	ctx := tool.NewContextFromCommand(command, tool.ContextOpts{
		Color:   &colorFlag,
		DryRun:  &dryRunFlag,
		Verbose: &verboseFlag,
	})
	client, err := createClient(ctx)
	if err != nil {
		return err
	}

	binaries, timestamp, err := latestBinaries(ctx, client)
	if err != nil {
		return err
	}
	if len(outputDirFlag) == 0 {
		outputDirFlag = fmt.Sprintf("./v23_%s_%s_%s", runtime.GOOS, runtime.GOARCH, timestamp)
	}
	if err := ctx.Run().MkdirAll(outputDirFlag, 0755); err != nil {
		return err
	}

	numBinaries := len(binaries)
	downloadBinaries := func() error {
		errChan := make(chan error, numBinaries)
		for _, name := range binaries {
			go downloadBinary(ctx, client, name, errChan)
		}
		gotError := false
		for i := 0; i < numBinaries; i++ {
			if err := <-errChan; err != nil {
				fmt.Fprintf(ctx.Stderr(), "failed to download binary: %v", err)
				gotError = true
			}
		}
		if gotError {
			if err := ctx.Run().RemoveAll(outputDirFlag); err != nil {
				fmt.Fprintf(ctx.Stderr(), "%v", err)
			}
			return fmt.Errorf("operation failed")
		}
		// Remove the .done file from the snapshot.
		if err := ctx.Run().RemoveAll(path.Join(outputDirFlag, ".done")); err != nil {
			return err
		}
		return nil
	}
	return ctx.Run().Function(downloadBinaries, fmt.Sprintf("Downloading binaries to %s", outputDirFlag))
}

// latestBinaries returns the binaries of the latest snapshot whose timestamp
// matches the datePrefixFlag, along with the matching timestamp.
func latestBinaries(ctx *tool.Context, client *http.Client) ([]string, string, error) {
	service, err := storage.New(client)
	if err != nil {
		return nil, "", err
	}
	timestamp, err := latestTimestamp(ctx, client, service)
	if err != nil {
		return nil, "", err
	}
	binaryPrefix := fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, timestamp)
	res, err := service.Objects.List(binariesBucketName).Fields("nextPageToken", "items/name").Prefix(binaryPrefix).Do()
	if err != nil {
		return nil, "", err
	}
	objs := res.Items
	for res.NextPageToken != "" {
		res, err = service.Objects.List(binariesBucketName).PageToken(res.NextPageToken).Do()
		if err != nil {
			return nil, "", err
		}
		objs = append(objs, res.Items...)
	}
	if len(objs) == 0 {
		return nil, "", fmt.Errorf("no binaries found (OS: %s, Arch: %s, Date: %s)", runtime.GOOS, runtime.GOARCH, timestamp)
	}
	ret := make([]string, len(objs))
	for i, obj := range objs {
		ret[i] = obj.Name
	}
	return ret, timestamp, nil
}

// latestTimestamp returns the time of the latest snapshot within the
// date-prefix range.
func latestTimestamp(ctx *tool.Context, client *http.Client, service *storage.Service) (string, error) {
	// If no datePrefixFlag is provided, we just want to get the latest snapshot.
	if datePrefixFlag == "" {
		latestFile := fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, "latest")
		b, err := downloadFileBytes(client, latestFile)
		if err != nil {
			return "", err
		}
		return string(b), nil
	}
	// Otherwise, we get the snapshots that match datePrefixFlag and choose the latest.
	snapshots, err := binarySnapshots(ctx, service)
	if err != nil {
		return "", err
	}
	const layout = "2006-01-02T15:04:05-07:00"
	var latest string
	var latestTime time.Time
	for _, name := range snapshots {
		spl := strings.Split(name, "/")
		timestamp := spl[1]
		t, err := time.Parse(layout, timestamp)
		if err != nil {
			return "", err
		}
		if t.After(latestTime) {
			latest = timestamp
			latestTime = t
		}
	}
	return latest, nil
}

func binarySnapshots(ctx *tool.Context, service *storage.Service) ([]string, error) {
	binaryPrefix := fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, datePrefixFlag)
	// We delimit results by the ".done" file to ensure that only successfully completed snapshots are considered.
	res, err := service.Objects.List(binariesBucketName).Fields("nextPageToken", "prefixes").Prefix(binaryPrefix).Delimiter("/.done").Do()
	if err != nil {
		return nil, err
	}
	snapshots := res.Prefixes
	for res.NextPageToken != "" {
		res, err = service.Objects.List(binariesBucketName).PageToken(res.NextPageToken).Do()
		if err != nil {
			return nil, err
		}
		snapshots = append(snapshots, res.Prefixes...)
	}
	if len(snapshots) == 0 {
		fmt.Fprintf(ctx.Stderr(), "no snapshots found (OS: %s, Arch: %s, Date: %s)\n", runtime.GOOS, runtime.GOARCH, datePrefixFlag)
		return nil, cmdline.ErrExitCode(NoValidSnapshotsExitCode)
	}
	ret := make([]string, len(snapshots))
	for i, snapshot := range snapshots {
		ret[i] = strings.TrimSuffix(snapshot, "/.done")
	}
	return ret, nil
}

func createClient(ctx *tool.Context) (*http.Client, error) {
	oauthHttpClient := &http.Client{}
	if len(keyFileFlag) > 0 {
		data, err := ctx.Run().ReadFile(keyFileFlag)
		if err != nil {
			return nil, err
		}
		conf, err := google.JWTConfigFromJSON(data, storage.CloudPlatformScope)
		if err != nil {
			return nil, fmt.Errorf("failed to create JWT config file: %v", err)
		}
		oauthHttpClient = conf.Client(oauth2.NoContext)
	}
	return oauthHttpClient, nil
}

func downloadBinary(ctx *tool.Context, client *http.Client, binaryPath string, errChan chan<- error) {
	helper := func() error {
		b, err := downloadFileBytes(client, binaryPath)
		if err != nil {
			return fmt.Errorf("failed to download file %v: %v", binaryPath, err)
		}
		fileName := filepath.Join(outputDirFlag, path.Base(binaryPath))
		if err := ctx.Run().WriteFile(fileName, b, 0755); err != nil {
			return err
		}
		return nil
	}
	errChan <- helper()
}

func downloadFileBytes(client *http.Client, filePath string) (b []byte, e error) {
	// This roundabout request is required because of the issue detailed here:
	// https://plus.sandbox.google.com/+IanRose/posts/Tzw3QZqEQZk
	// and here:
	// https://groups.google.com/forum/#!msg/Golang-nuts/juguXl-ss2Q/oOVFvHYqoSgJ.
	urls := "https://www.googleapis.com/download/storage/v1/b/{bucket}/o/{object}?alt=media"
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request to %s: %v\n", urls, err)
	}
	req.URL.Path = strings.Replace(req.URL.Path, "{bucket}", url.QueryEscape(binariesBucketName), 1)
	req.URL.Path = strings.Replace(req.URL.Path, "{object}", url.QueryEscape(filePath), 1)
	googleapi.SetOpaque(req.URL)
	res, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to download %v: %v\n", req.URL.RequestURI(), err)
	}
	if res.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("got StatusCode %v for download %v", req.URL.RequestURI(), res.StatusCode)
	}
	defer collect.Error(func() error { return res.Body.Close() }, &e)

	var buf bytes.Buffer
	if _, err := buf.ReadFrom(res.Body); err != nil {
		return nil, fmt.Errorf("failed to read response body: %v", err)
	}
	return buf.Bytes(), nil
}
<|endoftext|>


<commit_before>package termite

import (
	"github.com/hanwen/go-fuse/fuse"
)

const _NULL = "null"

type DevNullFs struct {
	fuse.DefaultNodeFileSystem
	root fuse.DefaultFsNode
}

func NewDevNullFs() *DevNullFs {
	me := &DevNullFs{}
	return me
}

func (me *DevNullFs) OnMount(fsc *fuse.FileSystemConnector) {
	n := me.root.Inode().NewSynthetic(false, &devNullNode{})
	me.root.Inode().AddChild("null", n)
}

func (me *DevNullFs) Root() fuse.FsNode {
	return &me.root
}

type devNullNode struct {
	fuse.DefaultFsNode
}

func (me *devNullNode) Access(mode uint32, context *fuse.Context) (code fuse.Status) {
	return fuse.OK
}

func (me *devNullNode) Truncate(file fuse.File, offset uint64, context *fuse.Context) (code fuse.Status) {
	return fuse.OK
}

func (me *devNullNode) Open(flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
	return fuse.NewDevNullFile(), fuse.OK
}
<commit_msg>Use Deletable() api.<commit_after>package termite

import (
	"github.com/hanwen/go-fuse/fuse"
)

const _NULL = "null"

type DevNullFs struct {
	fuse.DefaultNodeFileSystem
	root fuse.DefaultFsNode
}

func NewDevNullFs() *DevNullFs {
	me := &DevNullFs{}
	return me
}

func (me *DevNullFs) OnMount(fsc *fuse.FileSystemConnector) {
	n := me.root.Inode().New(false, &devNullNode{})
	me.root.Inode().AddChild("null", n)
}

func (me *DevNullFs) Root() fuse.FsNode {
	return &me.root
}

type devNullNode struct {
	fuse.DefaultFsNode
}

func (me *devNullNode) Deletable() bool {
	return false
}

func (me *devNullNode) Access(mode uint32, context *fuse.Context) (code fuse.Status) {
	return fuse.OK
}

func (me *devNullNode) Truncate(file fuse.File, offset uint64, context *fuse.Context) (code fuse.Status) {
	return fuse.OK
}

func (me *devNullNode) Open(flags uint32, context *fuse.Context) (file fuse.File, code fuse.Status) {
	return fuse.NewDevNullFile(), fuse.OK
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"

	"github.com/hashicorp/go-version"
)

// The main version number that is being run at the moment.
const Version = "0.7.9"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""

// SemVersion is an instance of version.Version. This has the secondary
// benefit of verifying during tests and init time that our version is a
// proper semantic version, which should always be the case.
var SemVersion = version.Must(version.NewVersion(Version))

// VersionHeader is the header name used to send the current terraform version
// in http requests.
const VersionHeader = "Terraform-Version"

func VersionString() string {
	if VersionPrerelease != "" {
		return fmt.Sprintf("%s-%s", Version, VersionPrerelease)
	}
	return Version
}
<commit_msg>release: cleanup after v0.7.9<commit_after>package terraform

import (
	"fmt"

	"github.com/hashicorp/go-version"
)

// The main version number that is being run at the moment.
const Version = "0.8.0"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "dev"

// SemVersion is an instance of version.Version. This has the secondary
// benefit of verifying during tests and init time that our version is a
// proper semantic version, which should always be the case.
var SemVersion = version.Must(version.NewVersion(Version))

// VersionHeader is the header name used to send the current terraform version
// in http requests.
const VersionHeader = "Terraform-Version"

func VersionString() string {
	if VersionPrerelease != "" {
		return fmt.Sprintf("%s-%s", Version, VersionPrerelease)
	}
	return Version
}
<|endoftext|>


<commit_before>package slack

// OutgoingMessage is used for the realtime API, and seems incomplete.
type OutgoingMessage struct {
	ID      int    `json:"id"`
	Channel string `json:"channel,omitempty"`
	Text    string `json:"text,omitempty"`
	Type    string `json:"type,omitempty"`
}

// Message is an auxiliary type to allow us to have a message containing sub messages
type Message struct {
	Msg
	SubMessage *Msg `json:"message,omitempty"`
}

// Msg contains information about a slack message
type Msg struct {
	// Basic Message
	Type            string       `json:"type,omitempty"`
	Channel         string       `json:"channel,omitempty"`
	User            string       `json:"user,omitempty"`
	Text            string       `json:"text,omitempty"`
	Timestamp       string       `json:"ts,omitempty"`
	ThreadTimeStamp string       `json:"thread_ts,omitempty"`
	IsStarred       bool         `json:"is_starred,omitempty"`
	PinnedTo        []string     `json:"pinned_to, omitempty"`
	Attachments     []Attachment `json:"attachments,omitempty"`
	Edited          *Edited      `json:"edited,omitempty"`

	// Message Subtypes
	SubType string `json:"subtype,omitempty"`

	// Hidden Subtypes
	Hidden           bool   `json:"hidden,omitempty"`     // message_changed, message_deleted, unpinned_item
	DeletedTimestamp string `json:"deleted_ts,omitempty"` // message_deleted
	EventTimestamp   string `json:"event_ts,omitempty"`

	// bot_message (https://api.slack.com/events/message/bot_message)
	BotID    string `json:"bot_id,omitempty"`
	Username string `json:"username,omitempty"`
	Icons    *Icon  `json:"icons,omitempty"`

	// channel_join, group_join
	Inviter string `json:"inviter,omitempty"`

	// channel_topic, group_topic
	Topic string `json:"topic,omitempty"`

	// channel_purpose, group_purpose
	Purpose string `json:"purpose,omitempty"`

	// channel_name, group_name
	Name    string `json:"name,omitempty"`
	OldName string `json:"old_name,omitempty"`

	// channel_archive, group_archive
	Members []string `json:"members,omitempty"`

	// file_share, file_comment, file_mention
	File *File `json:"file,omitempty"`

	// file_share
	Upload bool `json:"upload,omitempty"`

	// file_comment
	Comment *Comment `json:"comment,omitempty"`

	// pinned_item
	ItemType string `json:"item_type,omitempty"`

	// https://api.slack.com/rtm
	ReplyTo int    `json:"reply_to,omitempty"`
	Team    string `json:"team,omitempty"`

	// reactions
	Reactions []ItemReaction `json:"reactions,omitempty"`
}

// Icon is used for bot messages
type Icon struct {
	IconURL   string `json:"icon_url,omitempty"`
	IconEmoji string `json:"icon_emoji,omitempty"`
}

// Edited indicates that a message has been edited.
type Edited struct {
	User      string `json:"user,omitempty"`
	Timestamp string `json:"ts,omitempty"`
}

// Event contains the event type
type Event struct {
	Type string `json:"type,omitempty"`
}

// Ping contains information about a Ping Event
type Ping struct {
	ID   int    `json:"id"`
	Type string `json:"type"`
}

// Pong contains information about a Pong Event
type Pong struct {
	Type    string `json:"type"`
	ReplyTo int    `json:"reply_to"`
}

// NewOutgoingMessage prepares an OutgoingMessage that the user can
// use to send a message. Use this function to properly set the
// messageID.
func (rtm *RTM) NewOutgoingMessage(text string, channel string) *OutgoingMessage {
	id := rtm.idGen.Next()
	return &OutgoingMessage{
		ID:      id,
		Type:    "message",
		Channel: channel,
		Text:    text,
	}
}

// NewTypingMessage prepares an OutgoingMessage that the user can
// use to send as a typing indicator. Use this function to properly set the
// messageID.
func (rtm *RTM) NewTypingMessage(channel string) *OutgoingMessage {
	id := rtm.idGen.Next()
	return &OutgoingMessage{
		ID:      id,
		Type:    "typing",
		Channel: channel,
	}
}
<commit_msg>Rename ThreadTimeStamp to Threadtimestamp for consistency<commit_after>package slack

// OutgoingMessage is used for the realtime API, and seems incomplete.
type OutgoingMessage struct {
	ID      int    `json:"id"`
	Channel string `json:"channel,omitempty"`
	Text    string `json:"text,omitempty"`
	Type    string `json:"type,omitempty"`
}

// Message is an auxiliary type to allow us to have a message containing sub messages
type Message struct {
	Msg
	SubMessage *Msg `json:"message,omitempty"`
}

// Msg contains information about a slack message
type Msg struct {
	// Basic Message
	Type            string       `json:"type,omitempty"`
	Channel         string       `json:"channel,omitempty"`
	User            string       `json:"user,omitempty"`
	Text            string       `json:"text,omitempty"`
	Timestamp       string       `json:"ts,omitempty"`
	ThreadTimestamp string       `json:"thread_ts,omitempty"`
	IsStarred       bool         `json:"is_starred,omitempty"`
	PinnedTo        []string     `json:"pinned_to, omitempty"`
	Attachments     []Attachment `json:"attachments,omitempty"`
	Edited          *Edited      `json:"edited,omitempty"`

	// Message Subtypes
	SubType string `json:"subtype,omitempty"`

	// Hidden Subtypes
	Hidden           bool   `json:"hidden,omitempty"`     // message_changed, message_deleted, unpinned_item
	DeletedTimestamp string `json:"deleted_ts,omitempty"` // message_deleted
	EventTimestamp   string `json:"event_ts,omitempty"`

	// bot_message (https://api.slack.com/events/message/bot_message)
	BotID    string `json:"bot_id,omitempty"`
	Username string `json:"username,omitempty"`
	Icons    *Icon  `json:"icons,omitempty"`

	// channel_join, group_join
	Inviter string `json:"inviter,omitempty"`

	// channel_topic, group_topic
	Topic string `json:"topic,omitempty"`

	// channel_purpose, group_purpose
	Purpose string `json:"purpose,omitempty"`

	// channel_name, group_name
	Name    string `json:"name,omitempty"`
	OldName string `json:"old_name,omitempty"`

	// channel_archive, group_archive
	Members []string `json:"members,omitempty"`

	// file_share, file_comment, file_mention
	File *File `json:"file,omitempty"`

	// file_share
	Upload bool `json:"upload,omitempty"`

	// file_comment
	Comment *Comment `json:"comment,omitempty"`

	// pinned_item
	ItemType string `json:"item_type,omitempty"`

	// https://api.slack.com/rtm
	ReplyTo int    `json:"reply_to,omitempty"`
	Team    string `json:"team,omitempty"`

	// reactions
	Reactions []ItemReaction `json:"reactions,omitempty"`
}

// Icon is used for bot messages
type Icon struct {
	IconURL   string `json:"icon_url,omitempty"`
	IconEmoji string `json:"icon_emoji,omitempty"`
}

// Edited indicates that a message has been edited.
type Edited struct {
	User      string `json:"user,omitempty"`
	Timestamp string `json:"ts,omitempty"`
}

// Event contains the event type
type Event struct {
	Type string `json:"type,omitempty"`
}

// Ping contains information about a Ping Event
type Ping struct {
	ID   int    `json:"id"`
	Type string `json:"type"`
}

// Pong contains information about a Pong Event
type Pong struct {
	Type    string `json:"type"`
	ReplyTo int    `json:"reply_to"`
}

// NewOutgoingMessage prepares an OutgoingMessage that the user can
// use to send a message. Use this function to properly set the
// messageID.
func (rtm *RTM) NewOutgoingMessage(text string, channel string) *OutgoingMessage {
	id := rtm.idGen.Next()
	return &OutgoingMessage{
		ID:      id,
		Type:    "message",
		Channel: channel,
		Text:    text,
	}
}

// NewTypingMessage prepares an OutgoingMessage that the user can
// use to send as a typing indicator. Use this function to properly set the
// messageID.
func (rtm *RTM) NewTypingMessage(channel string) *OutgoingMessage {
	id := rtm.idGen.Next()
	return &OutgoingMessage{
		ID:      id,
		Type:    "typing",
		Channel: channel,
	}
}
<|endoftext|>