<commit_before>package hooks

import (
	"encoding/json"
	"os"
	"path/filepath"
	"strings"

	"github.com/cloudfoundry/libbuildpack"
)

type SnykCommand interface {
	Output(string, string, ...string) (string, error)
}

// SnykHook
type SnykHook struct {
	libbuildpack.DefaultHook
	Log         *libbuildpack.Logger
	SnykCommand SnykCommand
	buildDir    string
	depsDir     string
	localAgent  bool
	orgName     string
}

type SnykCredentials struct {
	ApiToken string
	ApiUrl   string
	OrgName  string
}

const snykLocalAgentPath = "node_modules/snyk/cli/index.js"

func init() {
	logger := libbuildpack.NewLogger(os.Stdout)
	command := &libbuildpack.Command{}

	libbuildpack.AddHook(SnykHook{
		Log:         logger,
		SnykCommand: command,
		buildDir:    "",
		depsDir:     "",
		localAgent:  true,
		orgName:     "",
	})
}

//Snyk hook
func (h SnykHook) AfterCompile(stager *libbuildpack.Stager) error {
	if h.isTokenExists() == false {
		h.Log.Debug("Snyk token wasn't found...")
		return nil
	}
	h.Log.Debug("Snyk token was found.")
	h.Log.BeginStep("Checking if Snyk service is enabled...")

	dontBreakBuild := strings.ToLower(os.Getenv("SNYK_DONT_BREAK_BUILD")) == "true"
	monitorBuild := strings.ToLower(os.Getenv("SNYK_MONITOR_BUILD")) == "true"
	protectBuild := strings.ToLower(os.Getenv("SNYK_PROTECT_BUILD")) == "true"
	orgName := strings.ToLower(os.Getenv("SNYK_ORG_NAME"))

	h.Log.Debug("SNYK_DONT_BREAK_BUILD is enabled: %t", dontBreakBuild)
	h.Log.Debug("SNYK_MONITOR_BUILD is enabled: %t", monitorBuild)
	h.Log.Debug("SNYK_PROTECT_BUILD is enabled: %t", protectBuild)

	h.buildDir = stager.BuildDir()
	h.depsDir = stager.DepDir()
	h.localAgent = true
	h.orgName = orgName

	snykExists := h.isAgentExists()
	if snykExists == false {
		h.localAgent = false
		if err := h.installAgent(); err != nil {
			return err
		}
	}

	// make a temporary link to depsDir next to package.json, as this is what
	// snyk cli expects.
	depsDirLocalPath := filepath.Join(h.buildDir, "node_modules")
	depsDirGlobalPath := filepath.Join(h.depsDir, "node_modules")
	if _, err := os.Lstat(depsDirLocalPath); os.IsNotExist(err) {
		h.Log.Debug("%s does not exist. making a temporary symlink %s -> %s",
			depsDirLocalPath, depsDirLocalPath, depsDirGlobalPath)

		err := os.Symlink(depsDirGlobalPath, depsDirLocalPath)
		if err != nil {
			return err
		}

		defer func() {
			h.Log.Debug("removing temporary link %s", depsDirLocalPath)
			os.Remove(depsDirLocalPath)
		}()
	}

	if protectBuild {
		if err := h.runProtect(); err != nil {
			return err
		}
	}

	successfulRun, err := h.runTest()
	if err != nil {
		if !successfulRun {
			return err
		}

		if !dontBreakBuild {
			h.Log.Error("Snyk found vulnerabilties. Failing build...")
			return err
		}
		h.Log.Warning("SNYK_DONT_BREAK_BUILD was defined, continue build despite vulnerabilities found")
	}

	if monitorBuild {
		err = h.runMonitor()
		if err != nil {
			return err
		}
	}
	h.Log.Info("Snyk finished successfully")
	return nil
}

func (h SnykHook) isTokenExists() bool {
	token := os.Getenv("SNYK_TOKEN")
	if token != "" {
		return true
	}

	status, snykCredentials := h.getCredentialsFromService()
	if status {
		os.Setenv("SNYK_TOKEN", snykCredentials.ApiToken)
		if snykCredentials.ApiUrl != "" {
			os.Setenv("SNYK_API", snykCredentials.ApiUrl)
		}
		if snykCredentials.OrgName != "" {
			os.Setenv("SNYK_ORG_NAME", snykCredentials.OrgName)
		}
		return true
	}
	return false
}

func (h SnykHook) isAgentExists() bool {
	h.Log.Debug("Checking if Snyk agent exists...")
	snykCliPath := filepath.Join(h.buildDir, snykLocalAgentPath)
	if _, err := os.Stat(snykCliPath); os.IsNotExist(err) {
		h.Log.Debug("Snyk agent doesn't exist")
		return false
	}

	h.Log.Debug("Snyk agent exists")
	return true
}

func (h SnykHook) installAgent() error {
	h.Log.Info("Installing Snyk agent...")
	output, err := h.SnykCommand.Output(h.buildDir, "npm", "install", "-g", "snyk")
	if err == nil {
		h.Log.Debug("Snyk agent installed %s", output)
		return nil
	}
	h.Log.Warning("Failed to install Snyk agent, please add snyk to your package.json dependecies.")
	return err
}

func (h SnykHook) runSnykCommand(args ...string) (string, error) {
	if h.orgName != "" {
		args = append(args, "--org="+h.orgName)
	}

	if os.Getenv("BP_DEBUG") != "" {
		args = append(args, "-d")
	}

	// Snyk is part of the app modules.
	if h.localAgent == true {
		snykCliPath := filepath.Join(h.buildDir, snykLocalAgentPath)
		snykArgs := append([]string{snykCliPath}, args...)
		return h.SnykCommand.Output(h.buildDir, "node", snykArgs...)
	}

	// Snyk is installed globally.
	snykGlobalAgentPath := filepath.Join(h.depsDir, "node", "bin", "snyk")
	return h.SnykCommand.Output(h.buildDir, snykGlobalAgentPath, args...)
}

func (h SnykHook) runTest() (bool, error) {
	h.Log.Debug("Run Snyk test...")
	output, err := h.runSnykCommand("test")
	if err == nil {
		h.Log.Info("Snyk test finished successfully - %s", output)
		return true, nil
	}
	//In case we got an unexpected output.
	if !strings.Contains(output, "dependencies for known") {
		h.Log.Warning("Failed to run Snyk agent - %s", output)
		h.Log.Warning("Please validate your auth token and that your npm version is equal or greater than v3.x.x")
		return false, err
	}
	h.Log.Warning("Snyk found vulnerabilties - %s", output)
	return true, err
}

func (h SnykHook) runMonitor() error {
	h.Log.Debug("Run Snyk monitor...")
	output, err := h.runSnykCommand("monitor", "--project-name="+h.appName())
	h.Log.Info("Snyk monitor %s", output)
	return err
}

func (h SnykHook) isPolicyFileExists() bool {
	h.Log.Debug("Check for Snyk policy file...")
	policyFilePath := filepath.Join(h.buildDir, ".snyk")
	if _, err := os.Stat(policyFilePath); os.IsNotExist(err) {
		return false
	}
	return true
}

func (h SnykHook) runProtect() error {
	if !h.isPolicyFileExists() {
		return nil
	}

	_, err := h.runSnykCommand("protect")
	return err
}

func getCredentialString(credentials map[string]interface{}, key string) string {
	value, isString := credentials[key].(string)

	if isString {
		return value
	}
	return ""
}

func (h SnykHook) getCredentialsFromService() (bool, SnykCredentials) {
	type Service struct {
		Name        string                 `json:"name"`
		Credentials map[string]interface{} `json:"credentials"`
	}
	var vcapServices map[string][]Service
	err := json.Unmarshal([]byte(os.Getenv("VCAP_SERVICES")), &vcapServices)
	if err != nil {
		h.Log.Warning("Failed to parse VCAP_SERVICES")
		return false, SnykCredentials{}
	}

	for key, services := range vcapServices {
		if strings.Contains(key, "snyk") {
			for _, service := range services {
				apiToken := getCredentialString(service.Credentials, "apiToken")
				if apiToken != "" {
					apiUrl := getCredentialString(service.Credentials, "apiUrl")
					orgName := getCredentialString(service.Credentials, "orgName")
					snykCredantials := SnykCredentials{
						ApiToken: apiToken,
						ApiUrl:   apiUrl,
						OrgName:  orgName,
					}
					return true, snykCredantials
				}
			}
		}
	}

	return false, SnykCredentials{}
}

func (h SnykHook) appName() string {
	var application struct {
		Name string `json:"name"`
	}
	err := json.Unmarshal([]byte(os.Getenv("VCAP_APPLICATION")), &application)
	if err != nil {
		return ""
	}

	return application.Name
}
<commit_msg>feat: add severity-threshold cli param<commit_after>package hooks

import (
	"encoding/json"
	"os"
	"path/filepath"
	"strings"

	"github.com/cloudfoundry/libbuildpack"
)

type SnykCommand interface {
	Output(string, string, ...string) (string, error)
}

// SnykHook
type SnykHook struct {
	libbuildpack.DefaultHook
	Log               *libbuildpack.Logger
	SnykCommand       SnykCommand
	buildDir          string
	depsDir           string
	localAgent        bool
	orgName           string
	severityThreshold string
}

type SnykCredentials struct {
	ApiToken string
	ApiUrl   string
	OrgName  string
}

const snykLocalAgentPath = "node_modules/snyk/cli/index.js"

func init() {
	logger := libbuildpack.NewLogger(os.Stdout)
	command := &libbuildpack.Command{}

	libbuildpack.AddHook(SnykHook{
		Log:               logger,
		SnykCommand:       command,
		buildDir:          "",
		depsDir:           "",
		localAgent:        true,
		orgName:           "",
		severityThreshold: "",
	})
}

//Snyk hook
func (h SnykHook) AfterCompile(stager *libbuildpack.Stager) error {
	if h.isTokenExists() == false {
		h.Log.Debug("Snyk token wasn't found...")
		return nil
	}
	h.Log.Debug("Snyk token was found.")
	h.Log.BeginStep("Checking if Snyk service is enabled...")

	dontBreakBuild := strings.ToLower(os.Getenv("SNYK_DONT_BREAK_BUILD")) == "true"
	monitorBuild := strings.ToLower(os.Getenv("SNYK_MONITOR_BUILD")) == "true"
	protectBuild := strings.ToLower(os.Getenv("SNYK_PROTECT_BUILD")) == "true"
	orgName := strings.ToLower(os.Getenv("SNYK_ORG_NAME"))
	severityThreshold := strings.ToLower(os.Getenv("SNYK_SEVERITY_THRESHOLD"))

	h.Log.Debug("SNYK_DONT_BREAK_BUILD is enabled: %t", dontBreakBuild)
	h.Log.Debug("SNYK_MONITOR_BUILD is enabled: %t", monitorBuild)
	h.Log.Debug("SNYK_PROTECT_BUILD is enabled: %t", protectBuild)
	if severityThreshold != "" {
		h.Log.Debug("SNYK_SEVERITY_THRESHOLD is set to: %s", severityThreshold)
	}

	h.buildDir = stager.BuildDir()
	h.depsDir = stager.DepDir()
	h.localAgent = true
	h.orgName = orgName
	h.severityThreshold = severityThreshold

	snykExists := h.isAgentExists()
	if snykExists == false {
		h.localAgent = false
		if err := h.installAgent(); err != nil {
			return err
		}
	}

	// make a temporary link to depsDir next to package.json, as this is what
	// snyk cli expects.
	depsDirLocalPath := filepath.Join(h.buildDir, "node_modules")
	depsDirGlobalPath := filepath.Join(h.depsDir, "node_modules")
	if _, err := os.Lstat(depsDirLocalPath); os.IsNotExist(err) {
		h.Log.Debug("%s does not exist. making a temporary symlink %s -> %s",
			depsDirLocalPath, depsDirLocalPath, depsDirGlobalPath)

		err := os.Symlink(depsDirGlobalPath, depsDirLocalPath)
		if err != nil {
			return err
		}

		defer func() {
			h.Log.Debug("removing temporary link %s", depsDirLocalPath)
			os.Remove(depsDirLocalPath)
		}()
	}

	if protectBuild {
		if err := h.runProtect(); err != nil {
			return err
		}
	}

	successfulRun, err := h.runTest()
	if err != nil {
		if !successfulRun {
			return err
		}

		if !dontBreakBuild {
			h.Log.Error("Snyk found vulnerabilties. Failing build...")
			return err
		}
		h.Log.Warning("SNYK_DONT_BREAK_BUILD was defined, continue build despite vulnerabilities found")
	}

	if monitorBuild {
		err = h.runMonitor()
		if err != nil {
			return err
		}
	}
	h.Log.Info("Snyk finished successfully")
	return nil
}

func (h SnykHook) isTokenExists() bool {
	token := os.Getenv("SNYK_TOKEN")
	if token != "" {
		return true
	}

	status, snykCredentials := h.getCredentialsFromService()
	if status {
		os.Setenv("SNYK_TOKEN", snykCredentials.ApiToken)
		if snykCredentials.ApiUrl != "" {
			os.Setenv("SNYK_API", snykCredentials.ApiUrl)
		}
		if snykCredentials.OrgName != "" {
			os.Setenv("SNYK_ORG_NAME", snykCredentials.OrgName)
		}
		return true
	}
	return false
}

func (h SnykHook) isAgentExists() bool {
	h.Log.Debug("Checking if Snyk agent exists...")
	snykCliPath := filepath.Join(h.buildDir, snykLocalAgentPath)
	if _, err := os.Stat(snykCliPath); os.IsNotExist(err) {
		h.Log.Debug("Snyk agent doesn't exist")
		return false
	}

	h.Log.Debug("Snyk agent exists")
	return true
}

func (h SnykHook) installAgent() error {
	h.Log.Info("Installing Snyk agent...")
	output, err := h.SnykCommand.Output(h.buildDir, "npm", "install", "-g", "snyk")
	if err == nil {
		h.Log.Debug("Snyk agent installed %s", output)
		return nil
	}
	h.Log.Warning("Failed to install Snyk agent, please add snyk to your package.json dependecies.")
	return err
}

func (h SnykHook) runSnykCommand(args ...string) (string, error) {
	if h.orgName != "" {
		args = append(args, "--org="+h.orgName)
	}

	if os.Getenv("BP_DEBUG") != "" {
		args = append(args, "-d")
	}

	if h.severityThreshold != "" {
		args = append(args, "--severity-threshold="+h.severityThreshold)
	}

	// Snyk is part of the app modules.
	if h.localAgent == true {
		snykCliPath := filepath.Join(h.buildDir, snykLocalAgentPath)
		snykArgs := append([]string{snykCliPath}, args...)
		return h.SnykCommand.Output(h.buildDir, "node", snykArgs...)
	}

	// Snyk is installed globally.
	snykGlobalAgentPath := filepath.Join(h.depsDir, "node", "bin", "snyk")
	return h.SnykCommand.Output(h.buildDir, snykGlobalAgentPath, args...)
}

func (h SnykHook) runTest() (bool, error) {
	h.Log.Debug("Run Snyk test...")
	output, err := h.runSnykCommand("test")
	if err == nil {
		h.Log.Info("Snyk test finished successfully - %s", output)
		return true, nil
	}
	//In case we got an unexpected output.
	if !strings.Contains(output, "dependencies for known") {
		h.Log.Warning("Failed to run Snyk agent - %s", output)
		h.Log.Warning("Please validate your auth token and that your npm version is equal or greater than v3.x.x")
		return false, err
	}
	h.Log.Warning("Snyk found vulnerabilties - %s", output)
	return true, err
}

func (h SnykHook) runMonitor() error {
	h.Log.Debug("Run Snyk monitor...")
	output, err := h.runSnykCommand("monitor", "--project-name="+h.appName())
	h.Log.Info("Snyk monitor %s", output)
	return err
}

func (h SnykHook) isPolicyFileExists() bool {
	h.Log.Debug("Check for Snyk policy file...")
	policyFilePath := filepath.Join(h.buildDir, ".snyk")
	if _, err := os.Stat(policyFilePath); os.IsNotExist(err) {
		return false
	}
	return true
}

func (h SnykHook) runProtect() error {
	if !h.isPolicyFileExists() {
		return nil
	}

	_, err := h.runSnykCommand("protect")
	return err
}

func getCredentialString(credentials map[string]interface{}, key string) string {
	value, isString := credentials[key].(string)

	if isString {
		return value
	}
	return ""
}

func (h SnykHook) getCredentialsFromService() (bool, SnykCredentials) {
	type Service struct {
		Name        string                 `json:"name"`
		Credentials map[string]interface{} `json:"credentials"`
	}
	var vcapServices map[string][]Service
	err := json.Unmarshal([]byte(os.Getenv("VCAP_SERVICES")), &vcapServices)
	if err != nil {
		h.Log.Warning("Failed to parse VCAP_SERVICES")
		return false, SnykCredentials{}
	}

	for key, services := range vcapServices {
		if strings.Contains(key, "snyk") {
			for _, service := range services {
				apiToken := getCredentialString(service.Credentials, "apiToken")
				if apiToken != "" {
					apiUrl := getCredentialString(service.Credentials, "apiUrl")
					orgName := getCredentialString(service.Credentials, "orgName")
					snykCredantials := SnykCredentials{
						ApiToken: apiToken,
						ApiUrl:   apiUrl,
						OrgName:  orgName,
					}
					return true, snykCredantials
				}
			}
		}
	}

	return false, SnykCredentials{}
}

func (h SnykHook) appName() string {
	var application struct {
		Name string `json:"name"`
	}
	err := json.Unmarshal([]byte(os.Getenv("VCAP_APPLICATION")), &application)
	if err != nil {
		return ""
	}

	return application.Name
}
<|endoftext|>


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

package nvim

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/garyburd/neovim-go/vim"
	"github.com/juju/errors"
)

var (
	ErrorColor    = "Identifier"
	ProgressColor = "Identifier"
	SuccessColor  = "Function"
)

// Echo provide the vim 'echo' command.
func Echo(v *vim.Vim, format string, a ...interface{}) error {
	v.Command("redraw")
	return v.Command("echo '" + fmt.Sprintf(format, a...) + "'")
}

// EchoRaw provide the raw output vim 'echo' command.
func EchoRaw(v *vim.Vim, a string) error {
	v.Command("redraw")
	return v.Command("echo \"" + a + "\"")
}

// Echomsg provide the vim 'echomsg' command.
func Echomsg(v *vim.Vim, a ...interface{}) error {
	v.Command("redraw")
	return v.Command("echomsg '" + strings.TrimSpace(fmt.Sprintln(a...)) + "'")
}

// Echoerr provide the vim 'echoerr' command.
func Echoerr(v *vim.Vim, format string, a ...interface{}) error {
	v.Command("redraw")
	return v.Command("echoerr '" + fmt.Sprintf(format, a...) + "'")
}

// ErrorWrap splits the errors.Annotate's cause and error messages,
// and provide the vim 'echo' message with 'echohl' highlighting to cause text.
func ErrorWrap(v *vim.Vim, err error) error {
	v.Command("redraw")
	er := strings.SplitAfterN(fmt.Sprintf("%s", err), ": ", 2)
	if os.Getenv("NVIM_GO_DEBUG") != "" {
		log.Printf("Error stack\n%s", errors.ErrorStack(err))
	}
	return v.Command("echo \"" + er[0] + "\" | echohl " + ErrorColor + " | echon \"" + er[1] + "\" | echohl None")
}

// EchohlErr provide the vim 'echo' command with the 'echohl' highlighting prefix text.
func EchohlErr(v *vim.Vim, prefix string, a ...interface{}) error {
	v.Command("redraw")
	if prefix != "" {
		prefix += ": "
	}
	er := fmt.Sprintf("%s", a...)
	return v.Command("echo '" + prefix + "' | echohl " + ErrorColor + " | echon \"" + er + "\" | echohl None")
}

// EchohlBefore provide the vim 'echo' command with the 'echohl' highlighting prefix text.
func EchohlBefore(v *vim.Vim, prefix string, highlight string, format string, a ...interface{}) error {
	v.Command("redraw")
	suffix := "\" | echohl None | echon \""
	if prefix != "" {
		suffix += ": "
	}
	return v.Command("echohl " + highlight + " | echo \"" + prefix + suffix + fmt.Sprintf(format, a...) + "\" | echohl None")
}

// EchohlAfter provide the vim 'echo' command with the 'echohl' highlighting message text.
func EchohlAfter(v *vim.Vim, prefix string, highlight string, format string, a ...interface{}) error {
	v.Command("redraw")
	if prefix != "" {
		prefix += ": "
	}
	return v.Command("echo \"" + prefix + "\" | echohl " + highlight + " | echon \"" + fmt.Sprintf(format, a...) + "\" | echohl None")
}

// EchoProgress displays a command progress message to echo area.
func EchoProgress(v *vim.Vim, prefix, format string, a ...interface{}) error {
	v.Command("redraw")
	msg := fmt.Sprintf(format, a...)
	return v.Command(fmt.Sprintf("echo \"%s: \" | echohl %s | echon \"%s ...\" | echohl None", prefix, ProgressColor, msg))
}

// EchoSuccess displays the success of the command to echo area.
func EchoSuccess(v *vim.Vim, prefix string, msg string) error {
	v.Command("redraw")
	if msg != "" {
		msg = " - " + msg
	}
	return v.Command(fmt.Sprintf("echo \"%s: \" | echohl %s | echon 'SUCCESS' | echohl None | echon \"%s\" | echohl None", prefix, SuccessColor, msg))
}

// ReportError output of the accumulated errors report.
// TODO(zchee): research vim.ReportError behavior
// Why it does not immediately display error?
func ReportError(v *vim.Vim, format string, a ...interface{}) error {
	return v.ReportError(fmt.Sprintf(format, a...))
}

// ClearMsg cleanups the echo area.
func ClearMsg(v *vim.Vim) error {
	return v.Command("echon")
}
<commit_msg>nvim/echo: Fix double-quote escape<commit_after>// Copyright 2016 Koichi Shiraishi. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package nvim

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/garyburd/neovim-go/vim"
	"github.com/juju/errors"
)

var (
	ErrorColor    = "Identifier"
	ProgressColor = "Identifier"
	SuccessColor  = "Function"
)

// Echo provide the vim 'echo' command.
func Echo(v *vim.Vim, format string, a ...interface{}) error {
	v.Command("redraw")
	return v.Command("echo '" + fmt.Sprintf(format, a...) + "'")
}

// EchoRaw provide the raw output vim 'echo' command.
func EchoRaw(v *vim.Vim, a string) error {
	v.Command("redraw")
	return v.Command("echo \"" + a + "\"")
}

// Echomsg provide the vim 'echomsg' command.
func Echomsg(v *vim.Vim, a ...interface{}) error {
	v.Command("redraw")
	return v.Command("echomsg '" + strings.TrimSpace(fmt.Sprintln(a...)) + "'")
}

// Echoerr provide the vim 'echoerr' command.
func Echoerr(v *vim.Vim, format string, a ...interface{}) error {
	v.Command("redraw")
	return v.Command("echoerr '" + fmt.Sprintf(format, a...) + "'")
}

// ErrorWrap splits the errors.Annotate's cause and error messages,
// and provide the vim 'echo' message with 'echohl' highlighting to cause text.
func ErrorWrap(v *vim.Vim, err error) error {
	v.Command("redraw")
	er := strings.SplitAfterN(fmt.Sprintf("%s", err), ": ", 2)
	if os.Getenv("NVIM_GO_DEBUG") != "" {
		log.Printf("Error stack\n%s", errors.ErrorStack(err))
	}
	return v.Command("echo \"" + er[0] + "\" | echohl " + ErrorColor + " | echon \"" + er[1] + "\" | echohl None")
}

// EchohlErr provide the vim 'echo' command with the 'echohl' highlighting prefix text.
func EchohlErr(v *vim.Vim, prefix string, a ...interface{}) error {
	v.Command("redraw")
	if prefix != "" {
		prefix += ": "
	}
	er := fmt.Sprintf("%s", a...)
	return v.Command("echo '" + prefix + "' | echohl " + ErrorColor + " | echon \"" + er + "\" | echohl None")
}

// EchohlBefore provide the vim 'echo' command with the 'echohl' highlighting prefix text.
func EchohlBefore(v *vim.Vim, prefix string, highlight string, format string, a ...interface{}) error {
	v.Command("redraw")
	suffix := "\" | echohl None | echon \""
	if prefix != "" {
		suffix += ": "
	}
	return v.Command("echohl " + highlight + " | echo \"" + prefix + suffix + fmt.Sprintf(format, a...) + "\" | echohl None")
}

// EchohlAfter provide the vim 'echo' command with the 'echohl' highlighting message text.
func EchohlAfter(v *vim.Vim, prefix string, highlight string, format string, a ...interface{}) error {
	v.Command("redraw")
	if prefix != "" {
		prefix += ": "
	}
	return v.Command("echo \"" + prefix + "\" | echohl " + highlight + " | echon \"" + fmt.Sprintf(format, a...) + "\" | echohl None")
}

// EchoProgress displays a command progress message to echo area.
func EchoProgress(v *vim.Vim, prefix, format string, a ...interface{}) error {
	v.Command("redraw")
	msg := fmt.Sprintf(format, a...)
	return v.Command(fmt.Sprintf("echo \"%s: \" | echohl %s | echon \"%s ...\" | echohl None", prefix, ProgressColor, msg))
}

// EchoSuccess displays the success of the command to echo area.
func EchoSuccess(v *vim.Vim, prefix string, msg string) error {
	v.Command("redraw")
	if msg != "" {
		msg = " - " + msg
	}
	return v.Command(fmt.Sprintf("echo \"%s: \" | echohl %s | echon 'SUCCESS' | echohl None | echon '%s' | echohl None", prefix, SuccessColor, msg))
}

// ReportError output of the accumulated errors report.
// TODO(zchee): research vim.ReportError behavior
// Why it does not immediately display error?
func ReportError(v *vim.Vim, format string, a ...interface{}) error {
	return v.ReportError(fmt.Sprintf(format, a...))
}

// ClearMsg cleanups the echo area.
func ClearMsg(v *vim.Vim) error {
	return v.Command("echon")
}
<|endoftext|>


<commit_before>package mackerel

import (
	"encoding/json"
	"fmt"
	"net/http"
)

// AWSIntegration aws integration information
type AWSIntegration struct {
	ID           string                            `json:"id"`
	Name         string                            `json:"name"`
	Memo         string                            `json:"memo"`
	Key          string                            `json:"key,omitempty"`
	RoleArn      string                            `json:"roleArn,omitempty"`
	ExternalID   string                            `json:"externalId,omitempty"`
	Region       string                            `json:"region"`
	IncludedTags string                            `json:"includedTags"`
	ExcludedTags string                            `json:"excludedTags"`
	Services     map[string]*AWSIntegrationService `json:"services"`
}

// AWSIntegrationService integration settings for each AWS service
type AWSIntegrationService struct {
	Enable              bool     `json:"enable"`
	Role                *string  `json:"role"`
	ExcludedMetrics     []string `json:"excludedMetrics"`
	RetireAutomatically bool     `json:"retireAutomatically,omitempty"`
}

// CreateAWSIntegrationParam  parameters for CreateAWSIntegration
type CreateAWSIntegrationParam struct {
	Name         string                            `json:"name"`
	Memo         string                            `json:"memo"`
	Key          string                            `json:"key,omitempty"`
	SecretKey    string                            `json:"secretKey,omitempty"`
	RoleArn      string                            `json:"roleArn,omitempty"`
	ExternalID   string                            `json:"externalId,omitempty"`
	Region       string                            `json:"region"`
	IncludedTags string                            `json:"includedTags"`
	ExcludedTags string                            `json:"excludedTags"`
	Services     map[string]*AWSIntegrationService `json:"services"`
}

// UpdateAWSIntegrationParam parameters for UpdateAwsIntegration
type UpdateAWSIntegrationParam struct {
	Name         string                            `json:"name"`
	Memo         string                            `json:"memo"`
	Key          string                            `json:"key,omitempty"`
	SecretKey    string                            `json:"secretKey,omitempty"`
	RoleArn      string                            `json:"roleArn,omitempty"`
	ExternalID   string                            `json:"externalId,omitempty"`
	Region       string                            `json:"region"`
	IncludedTags string                            `json:"includedTags"`
	ExcludedTags string                            `json:"excludedTags"`
	Services     map[string]*AWSIntegrationService `json:"services"`
}

// ListAWSIntegrationExcludableMetrics List of excludeable metric names for aws integration
type ListAWSIntegrationExcludableMetrics map[string][]string

// ListAWSIntegrations finds AWS Integration Settings
func (c *Client) ListAWSIntegrations() ([]*AWSIntegration, error) {
	req, err := http.NewRequest("GET", c.urlFor("/api/v0/aws-integrations").String(), nil)
	if err != nil {
		return nil, err
	}
	resp, err := c.Request(req)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var data struct {
		AwsIntegrations []*AWSIntegration `json:"aws_integrations"`
	}
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		return nil, err
	}
	return data.AwsIntegrations, err
}

// FindAWSIntegration lists AWS Integration Setting
func (c *Client) FindAWSIntegration(awsIntegrationID string) (*AWSIntegration, error) {
	req, err := http.NewRequest("GET", c.urlFor(fmt.Sprintf("/api/v0/aws-integrations/%s", awsIntegrationID)).String(), nil)
	if err != nil {
		return nil, err
	}
	resp, err := c.Request(req)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var awsIntegration *AWSIntegration
	err = json.NewDecoder(resp.Body).Decode(&awsIntegration)
	if err != nil {
		return nil, err
	}
	return awsIntegration, err
}

// CreateAWSIntegration creates AWS Integration Setting
func (c *Client) CreateAWSIntegration(param *CreateAWSIntegrationParam) (*AWSIntegration, error) {
	resp, err := c.PostJSON("/api/v0/aws-integrations", param)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var awsIntegration *AWSIntegration
	err = json.NewDecoder(resp.Body).Decode(&awsIntegration)
	if err != nil {
		return nil, err
	}
	return awsIntegration, err
}

// UpdateAWSIntegration updates AWS Integration Setting
func (c *Client) UpdateAWSIntegration(awsIntegrationID string, param *UpdateAWSIntegrationParam) (*AWSIntegration, error) {
	resp, err := c.PutJSON(fmt.Sprintf("/api/v0/aws-integrations/%s", awsIntegrationID), param)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var awsIntegration *AWSIntegration
	err = json.NewDecoder(resp.Body).Decode(&awsIntegration)
	if err != nil {
		return nil, err
	}
	return awsIntegration, err
}

// DeleteAWSIntegration deletes AWS Integration Setting
func (c *Client) DeleteAWSIntegration(awsIntegrationID string) (*AWSIntegration, error) {
	req, err := http.NewRequest(
		"DELETE",
		c.urlFor(fmt.Sprintf("/api/v0/aws-integrations/%s", awsIntegrationID)).String(),
		nil,
	)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := c.Request(req)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var awsIntegration *AWSIntegration
	err = json.NewDecoder(resp.Body).Decode(&awsIntegration)
	if err != nil {
		return nil, err
	}
	return awsIntegration, err
}

// CreateAWSIntegrationExternalID creates AWS Integration External ID
func (c *Client) CreateAWSIntegrationExternalID() (string, error) {
	resp, err := c.PostJSON("/api/v0/aws-integrations-external-id", nil)
	defer closeResponse(resp)
	if err != nil {
		return "", err
	}

	var data struct {
		ExternalID string `json:"externalId"`
	}
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		return "", err
	}
	return data.ExternalID, nil
}

// ListAWSIntegrationExcludableMetrics lists excludable metrics for AWS Integration
func (c *Client) ListAWSIntegrationExcludableMetrics() (*ListAWSIntegrationExcludableMetrics, error) {
	req, err := http.NewRequest("GET", c.urlFor("/api/v0/aws-integrations-excludable-metrics").String(), nil)
	if err != nil {
		return nil, err
	}
	resp, err := c.Request(req)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var listAWSIntegrationExcludableMetrics *ListAWSIntegrationExcludableMetrics
	err = json.NewDecoder(resp.Body).Decode(&listAWSIntegrationExcludableMetrics)
	if err != nil {
		return nil, err
	}
	return listAWSIntegrationExcludableMetrics, err
}
<commit_msg>UpdateAWSIntegrationParam type declaration correction<commit_after>package mackerel

import (
	"encoding/json"
	"fmt"
	"net/http"
)

// AWSIntegration aws integration information
type AWSIntegration struct {
	ID           string                            `json:"id"`
	Name         string                            `json:"name"`
	Memo         string                            `json:"memo"`
	Key          string                            `json:"key,omitempty"`
	RoleArn      string                            `json:"roleArn,omitempty"`
	ExternalID   string                            `json:"externalId,omitempty"`
	Region       string                            `json:"region"`
	IncludedTags string                            `json:"includedTags"`
	ExcludedTags string                            `json:"excludedTags"`
	Services     map[string]*AWSIntegrationService `json:"services"`
}

// AWSIntegrationService integration settings for each AWS service
type AWSIntegrationService struct {
	Enable              bool     `json:"enable"`
	Role                *string  `json:"role"`
	ExcludedMetrics     []string `json:"excludedMetrics"`
	RetireAutomatically bool     `json:"retireAutomatically,omitempty"`
}

// CreateAWSIntegrationParam  parameters for CreateAWSIntegration
type CreateAWSIntegrationParam struct {
	Name         string                            `json:"name"`
	Memo         string                            `json:"memo"`
	Key          string                            `json:"key,omitempty"`
	SecretKey    string                            `json:"secretKey,omitempty"`
	RoleArn      string                            `json:"roleArn,omitempty"`
	ExternalID   string                            `json:"externalId,omitempty"`
	Region       string                            `json:"region"`
	IncludedTags string                            `json:"includedTags"`
	ExcludedTags string                            `json:"excludedTags"`
	Services     map[string]*AWSIntegrationService `json:"services"`
}

// UpdateAWSIntegrationParam parameters for UpdateAwsIntegration
type UpdateAWSIntegrationParam CreateAWSIntegrationParam

// ListAWSIntegrationExcludableMetrics List of excludeable metric names for aws integration
type ListAWSIntegrationExcludableMetrics map[string][]string

// ListAWSIntegrations finds AWS Integration Settings
func (c *Client) ListAWSIntegrations() ([]*AWSIntegration, error) {
	req, err := http.NewRequest("GET", c.urlFor("/api/v0/aws-integrations").String(), nil)
	if err != nil {
		return nil, err
	}
	resp, err := c.Request(req)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var data struct {
		AwsIntegrations []*AWSIntegration `json:"aws_integrations"`
	}
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		return nil, err
	}
	return data.AwsIntegrations, err
}

// FindAWSIntegration lists AWS Integration Setting
func (c *Client) FindAWSIntegration(awsIntegrationID string) (*AWSIntegration, error) {
	req, err := http.NewRequest("GET", c.urlFor(fmt.Sprintf("/api/v0/aws-integrations/%s", awsIntegrationID)).String(), nil)
	if err != nil {
		return nil, err
	}
	resp, err := c.Request(req)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var awsIntegration *AWSIntegration
	err = json.NewDecoder(resp.Body).Decode(&awsIntegration)
	if err != nil {
		return nil, err
	}
	return awsIntegration, err
}

// CreateAWSIntegration creates AWS Integration Setting
func (c *Client) CreateAWSIntegration(param *CreateAWSIntegrationParam) (*AWSIntegration, error) {
	resp, err := c.PostJSON("/api/v0/aws-integrations", param)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var awsIntegration *AWSIntegration
	err = json.NewDecoder(resp.Body).Decode(&awsIntegration)
	if err != nil {
		return nil, err
	}
	return awsIntegration, err
}

// UpdateAWSIntegration updates AWS Integration Setting
func (c *Client) UpdateAWSIntegration(awsIntegrationID string, param *UpdateAWSIntegrationParam) (*AWSIntegration, error) {
	resp, err := c.PutJSON(fmt.Sprintf("/api/v0/aws-integrations/%s", awsIntegrationID), param)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var awsIntegration *AWSIntegration
	err = json.NewDecoder(resp.Body).Decode(&awsIntegration)
	if err != nil {
		return nil, err
	}
	return awsIntegration, err
}

// DeleteAWSIntegration deletes AWS Integration Setting
func (c *Client) DeleteAWSIntegration(awsIntegrationID string) (*AWSIntegration, error) {
	req, err := http.NewRequest(
		"DELETE",
		c.urlFor(fmt.Sprintf("/api/v0/aws-integrations/%s", awsIntegrationID)).String(),
		nil,
	)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := c.Request(req)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var awsIntegration *AWSIntegration
	err = json.NewDecoder(resp.Body).Decode(&awsIntegration)
	if err != nil {
		return nil, err
	}
	return awsIntegration, err
}

// CreateAWSIntegrationExternalID creates AWS Integration External ID
func (c *Client) CreateAWSIntegrationExternalID() (string, error) {
	resp, err := c.PostJSON("/api/v0/aws-integrations-external-id", nil)
	defer closeResponse(resp)
	if err != nil {
		return "", err
	}

	var data struct {
		ExternalID string `json:"externalId"`
	}
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		return "", err
	}
	return data.ExternalID, nil
}

// ListAWSIntegrationExcludableMetrics lists excludable metrics for AWS Integration
func (c *Client) ListAWSIntegrationExcludableMetrics() (*ListAWSIntegrationExcludableMetrics, error) {
	req, err := http.NewRequest("GET", c.urlFor("/api/v0/aws-integrations-excludable-metrics").String(), nil)
	if err != nil {
		return nil, err
	}
	resp, err := c.Request(req)
	defer closeResponse(resp)
	if err != nil {
		return nil, err
	}

	var listAWSIntegrationExcludableMetrics *ListAWSIntegrationExcludableMetrics
	err = json.NewDecoder(resp.Body).Decode(&listAWSIntegrationExcludableMetrics)
	if err != nil {
		return nil, err
	}
	return listAWSIntegrationExcludableMetrics, err
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/sagemaker"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
	"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/sagemaker/finder"
)

func init() {
	resource.AddTestSweepers("aws_sagemaker_image", &resource.Sweeper{
		Name: "aws_sagemaker_image",
		F:    testSweepSagemakerImages,
	})
}

func testSweepSagemakerImages(region string) error {
	client, err := sharedClientForRegion(region)
	if err != nil {
		return fmt.Errorf("error getting client: %s", err)
	}
	conn := client.(*AWSClient).sagemakerconn

	err = conn.ListImagesPages(&sagemaker.ListImagesInput{}, func(page *sagemaker.ListImagesOutput, lastPage bool) bool {
		for _, Image := range page.Images {
			name := aws.StringValue(Image.ImageName)

			input := &sagemaker.DeleteImageInput{
				ImageName: Image.ImageName,
			}

			log.Printf("[INFO] Deleting SageMaker Image: %s", name)
			if _, err := conn.DeleteImage(input); err != nil {
				log.Printf("[ERROR] Error deleting SageMaker Image (%s): %s", name, err)
				continue
			}
		}

		return !lastPage
	})

	if testSweepSkipSweepError(err) {
		log.Printf("[WARN] Skipping SageMaker Image sweep for %s: %s", region, err)
		return nil
	}

	if err != nil {
		return fmt.Errorf("Error retrieving SageMaker Images: %w", err)
	}

	return nil
}

func TestAccAWSSagemakerImage_basic(t *testing.T) {
	var notebook sagemaker.DescribeImageOutput
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_sagemaker_image.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerImageDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerImageBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerImageExists(resourceName, &notebook),
					resource.TestCheckResourceAttr(resourceName, "image_name", rName),
					testAccCheckResourceAttrRegionalARN(resourceName, "arn", "sagemaker", fmt.Sprintf("image/%s", rName)),
					resource.TestCheckResourceAttrPair(resourceName, "role_arn", "aws_iam_role.test", "arn"),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSSagemakerImage_disappears(t *testing.T) {
	var image sagemaker.DescribeImageOutput
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_sagemaker_image.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerImageDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerImageBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerImageExists(resourceName, &image),
					testAccCheckResourceDisappears(testAccProvider, resourceAwsSagemakerImage(), resourceName),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSSagemakerImageDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).sagemakerconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_sagemaker_image" {
			continue
		}

		Image, err := finder.ImageByName(conn, rs.Primary.ID)
		if err != nil {
			return nil
		}

		if aws.StringValue(Image.ImageName) == rs.Primary.ID {
			return fmt.Errorf("sagemaker Image %q still exists", rs.Primary.ID)
		}
	}

	return nil
}

func testAccCheckAWSSagemakerImageExists(n string, image *sagemaker.DescribeImageOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No sagmaker Image ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).sagemakerconn
		resp, err := finder.ImageByName(conn, rs.Primary.ID)
		if err != nil {
			return err
		}

		*image = *resp

		return nil
	}
}

func testAccAWSSagemakerImageConfigBase(rName string) string {
	return fmt.Sprintf(`
resource "aws_iam_role" "test" {
  name               = %[1]q
  path               = "/"
  assume_role_policy = data.aws_iam_policy_document.test.json
}

data "aws_iam_policy_document" "test" {
  statement {
	actions = ["sts:AssumeRole"]

	principals {
	  type        = "Service"
	  identifiers = ["sagemaker.amazonaws.com"]
	}
  }
}
`, rName)
}

func testAccAWSSagemakerImageBasicConfig(rName string) string {
	return testAccAWSSagemakerImageConfigBase(rName) + fmt.Sprintf(`
resource "aws_sagemaker_image" "test" {
  image_name = %[1]q
  role_arn   = aws_iam_role.test.arn
}
`, rName)
}
<commit_msg>add tags test<commit_after>package aws

import (
	"fmt"
	"log"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/sagemaker"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
	"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/sagemaker/finder"
)

func init() {
	resource.AddTestSweepers("aws_sagemaker_image", &resource.Sweeper{
		Name: "aws_sagemaker_image",
		F:    testSweepSagemakerImages,
	})
}

func testSweepSagemakerImages(region string) error {
	client, err := sharedClientForRegion(region)
	if err != nil {
		return fmt.Errorf("error getting client: %s", err)
	}
	conn := client.(*AWSClient).sagemakerconn

	err = conn.ListImagesPages(&sagemaker.ListImagesInput{}, func(page *sagemaker.ListImagesOutput, lastPage bool) bool {
		for _, Image := range page.Images {
			name := aws.StringValue(Image.ImageName)

			input := &sagemaker.DeleteImageInput{
				ImageName: Image.ImageName,
			}

			log.Printf("[INFO] Deleting SageMaker Image: %s", name)
			if _, err := conn.DeleteImage(input); err != nil {
				log.Printf("[ERROR] Error deleting SageMaker Image (%s): %s", name, err)
				continue
			}
		}

		return !lastPage
	})

	if testSweepSkipSweepError(err) {
		log.Printf("[WARN] Skipping SageMaker Image sweep for %s: %s", region, err)
		return nil
	}

	if err != nil {
		return fmt.Errorf("Error retrieving SageMaker Images: %w", err)
	}

	return nil
}

func TestAccAWSSagemakerImage_basic(t *testing.T) {
	var image sagemaker.DescribeImageOutput
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_sagemaker_image.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerImageDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerImageBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerImageExists(resourceName, &image),
					resource.TestCheckResourceAttr(resourceName, "image_name", rName),
					testAccCheckResourceAttrRegionalARN(resourceName, "arn", "sagemaker", fmt.Sprintf("image/%s", rName)),
					resource.TestCheckResourceAttrPair(resourceName, "role_arn", "aws_iam_role.test", "arn"),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSSagemakerImage_tags(t *testing.T) {
	var image sagemaker.DescribeImageOutput
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_sagemaker_image.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerImageDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerImageConfigTags1(rName, "key1", "value1"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerImageExists(resourceName, &image),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccAWSSagemakerImageConfigTags2(rName, "key1", "value1updated", "key2", "value2"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerImageExists(resourceName, &image),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"),
					resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
				),
			},
			{
				Config: testAccAWSSagemakerImageConfigTags1(rName, "key2", "value2"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerImageExists(resourceName, &image),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
				),
			},
		},
	})
}

func TestAccAWSSagemakerImage_disappears(t *testing.T) {
	var image sagemaker.DescribeImageOutput
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_sagemaker_image.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSSagemakerImageDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSSagemakerImageBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSSagemakerImageExists(resourceName, &image),
					testAccCheckResourceDisappears(testAccProvider, resourceAwsSagemakerImage(), resourceName),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSSagemakerImageDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).sagemakerconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_sagemaker_image" {
			continue
		}

		Image, err := finder.ImageByName(conn, rs.Primary.ID)
		if err != nil {
			return nil
		}

		if aws.StringValue(Image.ImageName) == rs.Primary.ID {
			return fmt.Errorf("sagemaker Image %q still exists", rs.Primary.ID)
		}
	}

	return nil
}

func testAccCheckAWSSagemakerImageExists(n string, image *sagemaker.DescribeImageOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No sagmaker Image ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).sagemakerconn
		resp, err := finder.ImageByName(conn, rs.Primary.ID)
		if err != nil {
			return err
		}

		*image = *resp

		return nil
	}
}

func testAccAWSSagemakerImageConfigBase(rName string) string {
	return fmt.Sprintf(`
resource "aws_iam_role" "test" {
  name               = %[1]q
  path               = "/"
  assume_role_policy = data.aws_iam_policy_document.test.json
}

data "aws_iam_policy_document" "test" {
  statement {
	actions = ["sts:AssumeRole"]

	principals {
	  type        = "Service"
	  identifiers = ["sagemaker.amazonaws.com"]
	}
  }
}
`, rName)
}

func testAccAWSSagemakerImageBasicConfig(rName string) string {
	return testAccAWSSagemakerImageConfigBase(rName) + fmt.Sprintf(`
resource "aws_sagemaker_image" "test" {
  image_name = %[1]q
  role_arn   = aws_iam_role.test.arn
}
`, rName)
}

func testAccAWSSagemakerImageConfigTags1(rName, tagKey1, tagValue1 string) string {
	return testAccAWSSagemakerImageConfigBase(rName) + fmt.Sprintf(`
resource "aws_sagemaker_image" "test" {
  image_name = %[1]q
  role_arn   = aws_iam_role.test.arn

  tags = {
    %[2]q = %[3]q
  }
}
`, rName, tagKey1, tagValue1)
}

func testAccAWSSagemakerImageConfigTags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string {
	return testAccAWSSagemakerImageConfigBase(rName) + fmt.Sprintf(`
resource "aws_sagemaker_image" "test" {
  image_name = %[1]q
  role_arn   = aws_iam_role.test.arn

  tags = {
    %[2]q = %[3]q
    %[4]q = %[5]q
  }
}
`, rName, tagKey1, tagValue1, tagKey2, tagValue2)
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package kola

import "github.com/coreos/mantle/kola/tests/coretest"

func init() {
	Register(&Test{
		Name:        "coretestsLocal",
		Run:         coretest.LocalTests,
		ClusterSize: 1,
		NativeFuncs: map[string]func() error{
			"CloudConfig":      coretest.TestCloudinitCloudConfig,
			"Script":           coretest.TestCloudinitScript,
			"PortSSH":          coretest.TestPortSsh,
			"DbusPerms":        coretest.TestDbusPerms,
			"Symlink":          coretest.TestSymlinkResolvConf,
			"UpdateEngineKeys": coretest.TestInstalledUpdateEngineRsaKeys,
			"ServicesActive":   coretest.TestServicesActive,
			"ReadOnly":         coretest.TestReadOnlyFs,
		},
	})
	Register(&Test{
		Name:        "coretestsCluster",
		Run:         coretest.ClusterTests,
		ClusterSize: 3,
		NativeFuncs: map[string]func() error{
			"EtcdUpdateValue":      coretest.TestEtcdUpdateValue,
			"FleetctlListMachines": coretest.TestFleetctlListMachines,
			"FleetctlRunService":   coretest.TestFleetctlRunService,
		},
		CloudConfig: `#cloud-config

coreos:
  etcd2:
    name: $name
    discovery: $discovery
    advertise-client-urls: http://$public_ipv4:2379
    initial-advertise-peer-urls: http://$private_ipv4:2380
    listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
    listen-peer-urls: http://$private_ipv4:2380,http://$private_ipv4:7001
  units:
    - name: etcd2.service
      command: start
    - name: fleet.service
      command: start`,
	})

	// tests requiring network connection to internet
	Register(&Test{
		Name:        "coretestsInternetLocal",
		Run:         coretest.InternetTests,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		NativeFuncs: map[string]func() error{
			"UpdateEngine": coretest.TestUpdateEngine,
			"DockerPing":   coretest.TestDockerPing,
			"DockerEcho":   coretest.TestDockerEcho,
			"NTPDate":      coretest.TestNTPDate,
		},
	})
}
<commit_msg>kola: comment out fleet coretests until stability fixed<commit_after>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package kola

import "github.com/coreos/mantle/kola/tests/coretest"

func init() {
	Register(&Test{
		Name:        "coretestsLocal",
		Run:         coretest.LocalTests,
		ClusterSize: 1,
		NativeFuncs: map[string]func() error{
			"CloudConfig":      coretest.TestCloudinitCloudConfig,
			"Script":           coretest.TestCloudinitScript,
			"PortSSH":          coretest.TestPortSsh,
			"DbusPerms":        coretest.TestDbusPerms,
			"Symlink":          coretest.TestSymlinkResolvConf,
			"UpdateEngineKeys": coretest.TestInstalledUpdateEngineRsaKeys,
			"ServicesActive":   coretest.TestServicesActive,
			"ReadOnly":         coretest.TestReadOnlyFs,
		},
	})
	Register(&Test{
		Name:        "coretestsCluster",
		Run:         coretest.ClusterTests,
		ClusterSize: 3,
		NativeFuncs: map[string]func() error{
			"EtcdUpdateValue": coretest.TestEtcdUpdateValue,
			// until stability improves comment out fleet tests
			//"FleetctlListMachines": coretest.TestFleetctlListMachines,
			//"FleetctlRunService":   coretest.TestFleetctlRunService,
		},
		CloudConfig: `#cloud-config

coreos:
  etcd2:
    name: $name
    discovery: $discovery
    advertise-client-urls: http://$public_ipv4:2379
    initial-advertise-peer-urls: http://$private_ipv4:2380
    listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
    listen-peer-urls: http://$private_ipv4:2380,http://$private_ipv4:7001
  units:
    - name: etcd2.service
      command: start
    - name: fleet.service
      command: start`,
	})

	// tests requiring network connection to internet
	Register(&Test{
		Name:        "coretestsInternetLocal",
		Run:         coretest.InternetTests,
		ClusterSize: 1,
		Platforms:   []string{"gce"},
		NativeFuncs: map[string]func() error{
			"UpdateEngine": coretest.TestUpdateEngine,
			"DockerPing":   coretest.TestDockerPing,
			"DockerEcho":   coretest.TestDockerEcho,
			"NTPDate":      coretest.TestNTPDate,
		},
	})
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"time"
)

type bashDeployer struct {
	clusterIPRange          string
	gcpProject              string
	gcpZone                 string
	gcpSSHProxyInstanceName string
	provider                string
}

var _ deployer = &bashDeployer{}

func newBash(clusterIPRange *string, gcpProject, gcpZone, gcpSSHProxyInstanceName, provider string) *bashDeployer {
	if *clusterIPRange == "" {
		if numNodes, err := strconv.Atoi(os.Getenv("NUM_NODES")); err == nil {
			*clusterIPRange = getClusterIPRange(numNodes)
		}
	}
	b := &bashDeployer{*clusterIPRange, gcpProject, gcpZone, gcpSSHProxyInstanceName, provider}
	return b
}

func (b *bashDeployer) Up() error {
	script := "./hack/e2e-internal/e2e-up.sh"
	cmd := exec.Command(script)
	cmd.Env = os.Environ()
	cmd.Env = append(cmd.Env, fmt.Sprintf("CLUSTER_IP_RANGE=%s", b.clusterIPRange))
	return control.FinishRunning(cmd)
}

func (b *bashDeployer) IsUp() error {
	return control.FinishRunning(exec.Command("./hack/e2e-internal/e2e-status.sh"))
}

func (b *bashDeployer) DumpClusterLogs(localPath, gcsPath string) error {
	return defaultDumpClusterLogs(localPath, gcsPath)
}

func (b *bashDeployer) TestSetup() error {
	if b.provider == "gce" && b.gcpSSHProxyInstanceName != "" {
		if err := setKubeShhBastionEnv(b.gcpProject, b.gcpZone, b.gcpSSHProxyInstanceName); err != nil {
			return err
		}
	}
	return nil
}

func (b *bashDeployer) Down() error {
	return control.FinishRunning(exec.Command("./hack/e2e-internal/e2e-down.sh"))
}

func (b *bashDeployer) GetClusterCreated(gcpProject string) (time.Time, error) {
	res, err := control.Output(exec.Command(
		"gcloud",
		"compute",
		"instance-groups",
		"list",
		"--project="+gcpProject,
		"--format=json(name,creationTimestamp)"))
	if err != nil {
		return time.Time{}, fmt.Errorf("list instance-group failed : %v", err)
	}

	created, err := getLatestClusterUpTime(string(res))
	if err != nil {
		return time.Time{}, fmt.Errorf("parse time failed : got gcloud res %s, err %v", string(res), err)
	}
	return created, nil
}

func (b *bashDeployer) KubectlCommand() (*exec.Cmd, error) { return nil, nil }

// Calculates the cluster IP range based on the no. of nodes in the cluster.
// Note: This mimics the function get-cluster-ip-range used by kube-up script.
func getClusterIPRange(numNodes int) string {
	suggestedRange := "10.64.0.0/14"
	if numNodes > 1000 {
		suggestedRange = "10.64.0.0/13"
	}
	if numNodes > 2000 {
		suggestedRange = "10.64.0.0/12"
	}
	if numNodes > 4000 {
		suggestedRange = "10.64.0.0/11"
	}
	return suggestedRange
}
<commit_msg>disable node logging by default for kubetest bash provider<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"time"
)

type bashDeployer struct {
	clusterIPRange          string
	gcpProject              string
	gcpZone                 string
	gcpSSHProxyInstanceName string
	provider                string
	nodeLoggingEnabled      bool
}

var _ deployer = &bashDeployer{}

var (
	bashNodeLogging = flag.Bool("bash-node-logging", false, "(bash only) enable node logging to gcp")
)

func newBash(clusterIPRange *string, gcpProject, gcpZone, gcpSSHProxyInstanceName, provider string) *bashDeployer {
	if *clusterIPRange == "" {
		if numNodes, err := strconv.Atoi(os.Getenv("NUM_NODES")); err == nil {
			*clusterIPRange = getClusterIPRange(numNodes)
		}
	}
	b := &bashDeployer{*clusterIPRange, gcpProject, gcpZone, gcpSSHProxyInstanceName, provider, *bashNodeLogging}
	return b
}

func (b *bashDeployer) Up() error {
	script := "./hack/e2e-internal/e2e-up.sh"
	cmd := exec.Command(script)
	cmd.Env = os.Environ()
	cmd.Env = append(cmd.Env, fmt.Sprintf("CLUSTER_IP_RANGE=%s", b.clusterIPRange))
	cmd.Env = append(cmd.Env, fmt.Sprintf("KUBE_ENABLE_NODE_LOGGING=%t", b.nodeLoggingEnabled))
	return control.FinishRunning(cmd)
}

func (b *bashDeployer) IsUp() error {
	return control.FinishRunning(exec.Command("./hack/e2e-internal/e2e-status.sh"))
}

func (b *bashDeployer) DumpClusterLogs(localPath, gcsPath string) error {
	return defaultDumpClusterLogs(localPath, gcsPath)
}

func (b *bashDeployer) TestSetup() error {
	if b.provider == "gce" && b.gcpSSHProxyInstanceName != "" {
		if err := setKubeShhBastionEnv(b.gcpProject, b.gcpZone, b.gcpSSHProxyInstanceName); err != nil {
			return err
		}
	}
	return nil
}

func (b *bashDeployer) Down() error {
	return control.FinishRunning(exec.Command("./hack/e2e-internal/e2e-down.sh"))
}

func (b *bashDeployer) GetClusterCreated(gcpProject string) (time.Time, error) {
	res, err := control.Output(exec.Command(
		"gcloud",
		"compute",
		"instance-groups",
		"list",
		"--project="+gcpProject,
		"--format=json(name,creationTimestamp)"))
	if err != nil {
		return time.Time{}, fmt.Errorf("list instance-group failed : %v", err)
	}

	created, err := getLatestClusterUpTime(string(res))
	if err != nil {
		return time.Time{}, fmt.Errorf("parse time failed : got gcloud res %s, err %v", string(res), err)
	}
	return created, nil
}

func (b *bashDeployer) KubectlCommand() (*exec.Cmd, error) { return nil, nil }

// Calculates the cluster IP range based on the no. of nodes in the cluster.
// Note: This mimics the function get-cluster-ip-range used by kube-up script.
func getClusterIPRange(numNodes int) string {
	suggestedRange := "10.64.0.0/14"
	if numNodes > 1000 {
		suggestedRange = "10.64.0.0/13"
	}
	if numNodes > 2000 {
		suggestedRange = "10.64.0.0/12"
	}
	if numNodes > 4000 {
		suggestedRange = "10.64.0.0/11"
	}
	return suggestedRange
}
<|endoftext|>


<commit_before>package main

import (
	"os/exec"
	"strings"
	"testing"
	"time"
)

func TestRestartStoppedContainer(t *testing.T) {
	defer deleteAllContainers()

	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "foobar")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out != "foobar\n" {
		t.Errorf("container should've printed 'foobar'")
	}

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out != "foobar\nfoobar\n" {
		t.Errorf("container should've printed 'foobar' twice")
	}

	logDone("restart - echo foobar for stopped container")
}

func TestRestartRunningContainer(t *testing.T) {
	defer deleteAllContainers()

	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "echo foobar && sleep 30 && echo 'should not print this'")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	cleanedContainerID := stripTrailingCharacters(out)

	time.Sleep(1 * time.Second)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out != "foobar\n" {
		t.Errorf("container should've printed 'foobar'")
	}

	runCmd = exec.Command(dockerBinary, "restart", "-t", "1", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	time.Sleep(1 * time.Second)

	if out != "foobar\nfoobar\n" {
		t.Errorf("container should've printed 'foobar' twice")
	}

	logDone("restart - echo foobar for running container")
}

// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
func TestRestartWithVolumes(t *testing.T) {
	defer deleteAllContainers()

	runCmd := exec.Command(dockerBinary, "run", "-d", "-v", "/test", "busybox", "top")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out = strings.Trim(out, " \n\r"); out != "1" {
		t.Errorf("expect 1 volume received %s", out)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
	volumes, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(volumes, err)
	}

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out = strings.Trim(out, " \n\r"); out != "1" {
		t.Errorf("expect 1 volume after restart received %s", out)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
	volumesAfterRestart, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(volumesAfterRestart, err)
	}

	if volumes != volumesAfterRestart {
		volumes = strings.Trim(volumes, " \n\r")
		volumesAfterRestart = strings.Trim(volumesAfterRestart, " \n\r")
		t.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
	}

	logDone("restart - does not create a new volume on restart")
}

func TestRestartPolicyNO(t *testing.T) {
	defer deleteAllContainers()

	cmd := exec.Command(dockerBinary, "run", "-d", "--restart=no", "busybox", "false")
	out, _, err := runCommandWithOutput(cmd)
	if err != nil {
		t.Fatal(err, out)
	}

	id := strings.TrimSpace(string(out))
	name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
	if err != nil {
		t.Fatal(err, out)
	}
	if name != "no" {
		t.Fatalf("Container restart policy name is %s, expected %s", name, "no")
	}

	logDone("restart - recording restart policy name for --restart=no")
}

func TestRestartPolicyAlways(t *testing.T) {
	defer deleteAllContainers()

	cmd := exec.Command(dockerBinary, "run", "-d", "--restart=always", "busybox", "false")
	out, _, err := runCommandWithOutput(cmd)
	if err != nil {
		t.Fatal(err, out)
	}

	id := strings.TrimSpace(string(out))
	name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
	if err != nil {
		t.Fatal(err, out)
	}
	if name != "always" {
		t.Fatalf("Container restart policy name is %s, expected %s", name, "always")
	}

	logDone("restart - recording restart policy name for --restart=always")
}

func TestRestartPolicyOnFailure(t *testing.T) {
	defer deleteAllContainers()

	cmd := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:1", "busybox", "false")
	out, _, err := runCommandWithOutput(cmd)
	if err != nil {
		t.Fatal(err, out)
	}

	id := strings.TrimSpace(string(out))
	name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
	if err != nil {
		t.Fatal(err, out)
	}
	if name != "on-failure" {
		t.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
	}

	logDone("restart - recording restart policy name for --restart=on-failure")
}

// a good container with --restart=on-failure:3
// MaximumRetryCount!=0; RestartCount=0
func TestContainerRestartwithGoodContainer(t *testing.T) {
	defer deleteAllContainers()
	out, err := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:3", "busybox", "true").CombinedOutput()
	if err != nil {
		t.Fatal(string(out), err)
	}
	id := strings.TrimSpace(string(out))
	if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5); err != nil {
		t.Fatal(err)
	}
	count, err := inspectField(id, "RestartCount")
	if err != nil {
		t.Fatal(err)
	}
	if count != "0" {
		t.Fatalf("Container was restarted %s times, expected %d", count, 0)
	}
	MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
	if err != nil {
		t.Fatal(err)
	}
	if MaximumRetryCount != "3" {
		t.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
	}

	logDone("restart - for a good container with restart policy, MaximumRetryCount is not 0 and RestartCount is 0")
}
<commit_msg>Verify MaximumRetryCount=0 if the restart policy is always.<commit_after>package main

import (
	"os/exec"
	"strings"
	"testing"
	"time"
)

func TestRestartStoppedContainer(t *testing.T) {
	defer deleteAllContainers()

	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "foobar")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out != "foobar\n" {
		t.Errorf("container should've printed 'foobar'")
	}

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out != "foobar\nfoobar\n" {
		t.Errorf("container should've printed 'foobar' twice")
	}

	logDone("restart - echo foobar for stopped container")
}

func TestRestartRunningContainer(t *testing.T) {
	defer deleteAllContainers()

	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "echo foobar && sleep 30 && echo 'should not print this'")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	cleanedContainerID := stripTrailingCharacters(out)

	time.Sleep(1 * time.Second)

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out != "foobar\n" {
		t.Errorf("container should've printed 'foobar'")
	}

	runCmd = exec.Command(dockerBinary, "restart", "-t", "1", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	time.Sleep(1 * time.Second)

	if out != "foobar\nfoobar\n" {
		t.Errorf("container should've printed 'foobar' twice")
	}

	logDone("restart - echo foobar for running container")
}

// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
func TestRestartWithVolumes(t *testing.T) {
	defer deleteAllContainers()

	runCmd := exec.Command(dockerBinary, "run", "-d", "-v", "/test", "busybox", "top")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out = strings.Trim(out, " \n\r"); out != "1" {
		t.Errorf("expect 1 volume received %s", out)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
	volumes, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(volumes, err)
	}

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if out = strings.Trim(out, " \n\r"); out != "1" {
		t.Errorf("expect 1 volume after restart received %s", out)
	}

	runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
	volumesAfterRestart, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(volumesAfterRestart, err)
	}

	if volumes != volumesAfterRestart {
		volumes = strings.Trim(volumes, " \n\r")
		volumesAfterRestart = strings.Trim(volumesAfterRestart, " \n\r")
		t.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
	}

	logDone("restart - does not create a new volume on restart")
}

func TestRestartPolicyNO(t *testing.T) {
	defer deleteAllContainers()

	cmd := exec.Command(dockerBinary, "run", "-d", "--restart=no", "busybox", "false")
	out, _, err := runCommandWithOutput(cmd)
	if err != nil {
		t.Fatal(err, out)
	}

	id := strings.TrimSpace(string(out))
	name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
	if err != nil {
		t.Fatal(err, out)
	}
	if name != "no" {
		t.Fatalf("Container restart policy name is %s, expected %s", name, "no")
	}

	logDone("restart - recording restart policy name for --restart=no")
}

func TestRestartPolicyAlways(t *testing.T) {
	defer deleteAllContainers()

	cmd := exec.Command(dockerBinary, "run", "-d", "--restart=always", "busybox", "false")
	out, _, err := runCommandWithOutput(cmd)
	if err != nil {
		t.Fatal(err, out)
	}

	id := strings.TrimSpace(string(out))
	name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
	if err != nil {
		t.Fatal(err, out)
	}
	if name != "always" {
		t.Fatalf("Container restart policy name is %s, expected %s", name, "always")
	}

	MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
	if err != nil {
		t.Fatal(err)
	}

	// MaximumRetryCount=0 if the restart policy is always
	if MaximumRetryCount != "0" {
		t.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "0")
	}

	logDone("restart - recording restart policy name for --restart=always")
}

func TestRestartPolicyOnFailure(t *testing.T) {
	defer deleteAllContainers()

	cmd := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:1", "busybox", "false")
	out, _, err := runCommandWithOutput(cmd)
	if err != nil {
		t.Fatal(err, out)
	}

	id := strings.TrimSpace(string(out))
	name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
	if err != nil {
		t.Fatal(err, out)
	}
	if name != "on-failure" {
		t.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
	}

	logDone("restart - recording restart policy name for --restart=on-failure")
}

// a good container with --restart=on-failure:3
// MaximumRetryCount!=0; RestartCount=0
func TestContainerRestartwithGoodContainer(t *testing.T) {
	defer deleteAllContainers()
	out, err := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:3", "busybox", "true").CombinedOutput()
	if err != nil {
		t.Fatal(string(out), err)
	}
	id := strings.TrimSpace(string(out))
	if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5); err != nil {
		t.Fatal(err)
	}
	count, err := inspectField(id, "RestartCount")
	if err != nil {
		t.Fatal(err)
	}
	if count != "0" {
		t.Fatalf("Container was restarted %s times, expected %d", count, 0)
	}
	MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
	if err != nil {
		t.Fatal(err)
	}
	if MaximumRetryCount != "3" {
		t.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
	}

	logDone("restart - for a good container with restart policy, MaximumRetryCount is not 0 and RestartCount is 0")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"net/http"

	"github.com/bborbe/log"
	"github.com/bborbe/portfolio/handler"
	"github.com/facebookgo/grace/gracehttp"
	"os"
)

const (
	PARAMETER_LOGLEVEL = "loglevel"
)

var (
	logger = log.DefaultLogger
	addressPtr = flag.String("a0", ":48568", "Zero address to bind to.")
	documentRootPtr = flag.String("root", "", "Document root directory")
	logLevelPtr = flag.String(PARAMETER_LOGLEVEL, log.INFO_STRING, log.FLAG_USAGE)
)

func main() {
	defer logger.Close()
	flag.Parse()

	logger.SetLevelThreshold(log.LogStringToLevel(*logLevelPtr))
	logger.Debugf("set log level to %s", *logLevelPtr)

	server, err := createServer(*addressPtr, *documentRootPtr)
	if err != nil {
		logger.Fatal(err)
		logger.Close()
		os.Exit(1)
	}
	logger.Debugf("start server")
	gracehttp.Serve(server)
}

func createServer(address string, documentRoot string) (*http.Server, error) {
	return &http.Server{Addr: address, Handler: handler.NewHandler(documentRoot)}, nil
}
<commit_msg>update server<commit_after>package main

import (
	"flag"
	"net/http"

	"os"

	"github.com/bborbe/log"
	"github.com/bborbe/portfolio/handler"
	"github.com/facebookgo/grace/gracehttp"
)

const (
	PARAMETER_LOGLEVEL = "loglevel"
)

var (
	logger          = log.DefaultLogger
	addressPtr      = flag.String("a0", ":48568", "Zero address to bind to.")
	documentRootPtr = flag.String("root", "", "Document root directory")
	logLevelPtr     = flag.String(PARAMETER_LOGLEVEL, log.INFO_STRING, log.FLAG_USAGE)
)

func main() {
	defer logger.Close()
	flag.Parse()

	logger.SetLevelThreshold(log.LogStringToLevel(*logLevelPtr))
	logger.Debugf("set log level to %s", *logLevelPtr)

	server, err := createServer(*addressPtr, *documentRootPtr)
	if err != nil {
		logger.Fatal(err)
		logger.Close()
		os.Exit(1)
	}
	logger.Debugf("start server")
	gracehttp.Serve(server)
}

func createServer(address string, documentRoot string) (*http.Server, error) {
	return &http.Server{Addr: address, Handler: handler.NewHandler(documentRoot)}, nil
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go 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 ast

import (
	"go/token"
	"sort"
	"strconv"
)

// SortImports sorts runs of consecutive import lines in import blocks in f.
func SortImports(fset *token.FileSet, f *File) {
	for _, d := range f.Decls {
		d, ok := d.(*GenDecl)
		if !ok || d.Tok != token.IMPORT {
			// Not an import declaration, so we're done.
			// Imports are always first.
			break
		}

		if d.Lparen == token.NoPos {
			// Not a block: sorted by default.
			continue
		}

		// Identify and sort runs of specs on successive lines.
		i := 0
		for j, s := range d.Specs {
			if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line {
				// j begins a new run.  End this one.
				sortSpecs(fset, f, d.Specs[i:j])
				i = j
			}
		}
		sortSpecs(fset, f, d.Specs[i:])
	}
}

func importPath(s Spec) string {
	t, err := strconv.Unquote(s.(*ImportSpec).Path.Value)
	if err == nil {
		return t
	}
	return ""
}

type posSpan struct {
	Start token.Pos
	End   token.Pos
}

func sortSpecs(fset *token.FileSet, f *File, specs []Spec) {
	// Avoid work if already sorted (also catches < 2 entries).
	sorted := true
	for i, s := range specs {
		if i > 0 && importPath(specs[i-1]) > importPath(s) {
			sorted = false
			break
		}
	}
	if sorted {
		return
	}

	// Record positions for specs.
	pos := make([]posSpan, len(specs))
	for i, s := range specs {
		pos[i] = posSpan{s.Pos(), s.End()}
	}

	// Identify comments in this range.
	// Any comment from pos[0].Start to the final line counts.
	lastLine := fset.Position(pos[len(pos)-1].End).Line
	cstart := len(f.Comments)
	cend := len(f.Comments)
	for i, g := range f.Comments {
		if g.Pos() < pos[0].Start {
			continue
		}
		if i < cstart {
			cstart = i
		}
		if fset.Position(g.End()).Line > lastLine {
			cend = i
			break
		}
	}
	comments := f.Comments[cstart:cend]

	// Assign each comment to the import spec preceding it.
	importComment := map[*ImportSpec][]*CommentGroup{}
	specIndex := 0
	for _, g := range comments {
		for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() {
			specIndex++
		}
		s := specs[specIndex].(*ImportSpec)
		importComment[s] = append(importComment[s], g)
	}

	// Sort the import specs by import path.
	// Reassign the import paths to have the same position sequence.
	// Reassign each comment to abut the end of its spec.
	// Sort the comments by new position.
	sort.Sort(byImportPath(specs))
	for i, s := range specs {
		s := s.(*ImportSpec)
		if s.Name != nil {
			s.Name.NamePos = pos[i].Start
		}
		s.Path.ValuePos = pos[i].Start
		s.EndPos = pos[i].End
		for _, g := range importComment[s] {
			for _, c := range g.List {
				c.Slash = pos[i].End
			}
		}
	}
	sort.Sort(byCommentPos(comments))
}

type byImportPath []Spec // slice of *ImportSpec

func (x byImportPath) Len() int           { return len(x) }
func (x byImportPath) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
func (x byImportPath) Less(i, j int) bool { return importPath(x[i]) < importPath(x[j]) }

type byCommentPos []*CommentGroup

func (x byCommentPos) Len() int           { return len(x) }
func (x byCommentPos) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }
<commit_msg>go/ast: minor cleanup<commit_after>// Copyright 2011 The Go 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 ast

import (
	"go/token"
	"sort"
	"strconv"
)

// SortImports sorts runs of consecutive import lines in import blocks in f.
func SortImports(fset *token.FileSet, f *File) {
	for _, d := range f.Decls {
		d, ok := d.(*GenDecl)
		if !ok || d.Tok != token.IMPORT {
			// Not an import declaration, so we're done.
			// Imports are always first.
			break
		}

		if !d.Lparen.IsValid() {
			// Not a block: sorted by default.
			continue
		}

		// Identify and sort runs of specs on successive lines.
		i := 0
		for j, s := range d.Specs {
			if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line {
				// j begins a new run.  End this one.
				sortSpecs(fset, f, d.Specs[i:j])
				i = j
			}
		}
		sortSpecs(fset, f, d.Specs[i:])
	}
}

func importPath(s Spec) string {
	t, err := strconv.Unquote(s.(*ImportSpec).Path.Value)
	if err == nil {
		return t
	}
	return ""
}

type posSpan struct {
	Start token.Pos
	End   token.Pos
}

func sortSpecs(fset *token.FileSet, f *File, specs []Spec) {
	// Avoid work if already sorted (also catches < 2 entries).
	sorted := true
	for i, s := range specs {
		if i > 0 && importPath(specs[i-1]) > importPath(s) {
			sorted = false
			break
		}
	}
	if sorted {
		return
	}

	// Record positions for specs.
	pos := make([]posSpan, len(specs))
	for i, s := range specs {
		pos[i] = posSpan{s.Pos(), s.End()}
	}

	// Identify comments in this range.
	// Any comment from pos[0].Start to the final line counts.
	lastLine := fset.Position(pos[len(pos)-1].End).Line
	cstart := len(f.Comments)
	cend := len(f.Comments)
	for i, g := range f.Comments {
		if g.Pos() < pos[0].Start {
			continue
		}
		if i < cstart {
			cstart = i
		}
		if fset.Position(g.End()).Line > lastLine {
			cend = i
			break
		}
	}
	comments := f.Comments[cstart:cend]

	// Assign each comment to the import spec preceding it.
	importComment := map[*ImportSpec][]*CommentGroup{}
	specIndex := 0
	for _, g := range comments {
		for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() {
			specIndex++
		}
		s := specs[specIndex].(*ImportSpec)
		importComment[s] = append(importComment[s], g)
	}

	// Sort the import specs by import path.
	// Reassign the import paths to have the same position sequence.
	// Reassign each comment to abut the end of its spec.
	// Sort the comments by new position.
	sort.Sort(byImportPath(specs))
	for i, s := range specs {
		s := s.(*ImportSpec)
		if s.Name != nil {
			s.Name.NamePos = pos[i].Start
		}
		s.Path.ValuePos = pos[i].Start
		s.EndPos = pos[i].End
		for _, g := range importComment[s] {
			for _, c := range g.List {
				c.Slash = pos[i].End
			}
		}
	}
	sort.Sort(byCommentPos(comments))
}

type byImportPath []Spec // slice of *ImportSpec

func (x byImportPath) Len() int           { return len(x) }
func (x byImportPath) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
func (x byImportPath) Less(i, j int) bool { return importPath(x[i]) < importPath(x[j]) }

type byCommentPos []*CommentGroup

func (x byCommentPos) Len() int           { return len(x) }
func (x byCommentPos) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }
<|endoftext|>


<commit_before>// Copyright 2011 The Go 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 build

import (
	"errors"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
)

// Path is a validated list of Trees derived from $GOROOT and $GOPATH at init.
var Path []*Tree

// Tree describes a Go source tree, either $GOROOT or one from $GOPATH.
type Tree struct {
	Path   string
	Goroot bool
}

func newTree(p string) (*Tree, error) {
	if !filepath.IsAbs(p) {
		return nil, errors.New("must be absolute")
	}
	ep, err := filepath.EvalSymlinks(p)
	if err != nil {
		return nil, err
	}
	return &Tree{Path: ep}, nil
}

// SrcDir returns the tree's package source directory.
func (t *Tree) SrcDir() string {
	if t.Goroot {
		return filepath.Join(t.Path, "src", "pkg")
	}
	return filepath.Join(t.Path, "src")
}

// PkgDir returns the tree's package object directory.
func (t *Tree) PkgDir() string {
	goos, goarch := runtime.GOOS, runtime.GOARCH
	if e := os.Getenv("GOOS"); e != "" {
		goos = e
	}
	if e := os.Getenv("GOARCH"); e != "" {
		goarch = e
	}
	return filepath.Join(t.Path, "pkg", goos+"_"+goarch)
}

// BinDir returns the tree's binary executable directory.
func (t *Tree) BinDir() string {
	if t.Goroot {
		if gobin := os.Getenv("GOBIN"); gobin != "" {
			return gobin
		}
	}
	return filepath.Join(t.Path, "bin")
}

// HasSrc returns whether the given package's
// source can be found inside this Tree.
func (t *Tree) HasSrc(pkg string) bool {
	fi, err := os.Stat(filepath.Join(t.SrcDir(), pkg))
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// HasPkg returns whether the given package's
// object file can be found inside this Tree.
func (t *Tree) HasPkg(pkg string) bool {
	fi, err := os.Stat(filepath.Join(t.PkgDir(), pkg+".a"))
	if err != nil {
		return false
	}
	return !fi.IsDir()
	// TODO(adg): check object version is consistent
}

var (
	ErrNotFound     = errors.New("package could not be found locally")
	ErrTreeNotFound = errors.New("no valid GOROOT or GOPATH could be found")
)

// FindTree takes an import or filesystem path and returns the
// tree where the package source should be and the package import path.
func FindTree(path string) (tree *Tree, pkg string, err error) {
	if isLocalPath(path) {
		if path, err = filepath.Abs(path); err != nil {
			return
		}
		if path, err = filepath.EvalSymlinks(path); err != nil {
			return
		}
		for _, t := range Path {
			tpath := t.SrcDir() + string(filepath.Separator)
			if !filepath.HasPrefix(path, tpath) {
				continue
			}
			tree = t
			pkg = path[len(tpath):]
			return
		}
		err = fmt.Errorf("path %q not inside a GOPATH", path)
		return
	}
	tree = defaultTree
	pkg = path
	for _, t := range Path {
		if t.HasSrc(pkg) {
			tree = t
			return
		}
	}
	if tree == nil {
		err = ErrTreeNotFound
	} else {
		err = ErrNotFound
	}
	return
}

// isLocalPath returns whether the given path is local (/foo ./foo ../foo . ..)
// Windows paths that starts with drive letter (c:\foo c:foo) are considered local.
func isLocalPath(s string) bool {
	const sep = string(filepath.Separator)
	return s == "." || s == ".." ||
		filepath.HasPrefix(s, sep) ||
		filepath.HasPrefix(s, "."+sep) || filepath.HasPrefix(s, ".."+sep) ||
		filepath.VolumeName(s) != ""
}

var (
	// argument lists used by the build's gc and ld methods
	gcImportArgs []string
	ldImportArgs []string

	// default tree for remote packages
	defaultTree *Tree
)

// set up Path: parse and validate GOROOT and GOPATH variables
func init() {
	root := runtime.GOROOT()
	t, err := newTree(root)
	if err != nil {
		log.Printf("invalid GOROOT %q: %v", root, err)
	} else {
		t.Goroot = true
		Path = []*Tree{t}
	}

	for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
		if p == "" {
			continue
		}
		t, err := newTree(p)
		if err != nil {
			log.Printf("invalid GOPATH %q: %v", p, err)
			continue
		}
		Path = append(Path, t)
		gcImportArgs = append(gcImportArgs, "-I", t.PkgDir())
		ldImportArgs = append(ldImportArgs, "-L", t.PkgDir())

		// select first GOPATH entry as default
		if defaultTree == nil {
			defaultTree = t
		}
	}

	// use GOROOT if no valid GOPATH specified
	if defaultTree == nil && len(Path) > 0 {
		defaultTree = Path[0]
	}
}
<commit_msg>go/build: (*Tree).BinDir should not return path with / in it on windows<commit_after>// Copyright 2011 The Go 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 build

import (
	"errors"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
)

// Path is a validated list of Trees derived from $GOROOT and $GOPATH at init.
var Path []*Tree

// Tree describes a Go source tree, either $GOROOT or one from $GOPATH.
type Tree struct {
	Path   string
	Goroot bool
}

func newTree(p string) (*Tree, error) {
	if !filepath.IsAbs(p) {
		return nil, errors.New("must be absolute")
	}
	ep, err := filepath.EvalSymlinks(p)
	if err != nil {
		return nil, err
	}
	return &Tree{Path: ep}, nil
}

// SrcDir returns the tree's package source directory.
func (t *Tree) SrcDir() string {
	if t.Goroot {
		return filepath.Join(t.Path, "src", "pkg")
	}
	return filepath.Join(t.Path, "src")
}

// PkgDir returns the tree's package object directory.
func (t *Tree) PkgDir() string {
	goos, goarch := runtime.GOOS, runtime.GOARCH
	if e := os.Getenv("GOOS"); e != "" {
		goos = e
	}
	if e := os.Getenv("GOARCH"); e != "" {
		goarch = e
	}
	return filepath.Join(t.Path, "pkg", goos+"_"+goarch)
}

// BinDir returns the tree's binary executable directory.
func (t *Tree) BinDir() string {
	if t.Goroot {
		if gobin := os.Getenv("GOBIN"); gobin != "" {
			return filepath.Clean(gobin)
		}
	}
	return filepath.Join(t.Path, "bin")
}

// HasSrc returns whether the given package's
// source can be found inside this Tree.
func (t *Tree) HasSrc(pkg string) bool {
	fi, err := os.Stat(filepath.Join(t.SrcDir(), pkg))
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// HasPkg returns whether the given package's
// object file can be found inside this Tree.
func (t *Tree) HasPkg(pkg string) bool {
	fi, err := os.Stat(filepath.Join(t.PkgDir(), pkg+".a"))
	if err != nil {
		return false
	}
	return !fi.IsDir()
	// TODO(adg): check object version is consistent
}

var (
	ErrNotFound     = errors.New("package could not be found locally")
	ErrTreeNotFound = errors.New("no valid GOROOT or GOPATH could be found")
)

// FindTree takes an import or filesystem path and returns the
// tree where the package source should be and the package import path.
func FindTree(path string) (tree *Tree, pkg string, err error) {
	if isLocalPath(path) {
		if path, err = filepath.Abs(path); err != nil {
			return
		}
		if path, err = filepath.EvalSymlinks(path); err != nil {
			return
		}
		for _, t := range Path {
			tpath := t.SrcDir() + string(filepath.Separator)
			if !filepath.HasPrefix(path, tpath) {
				continue
			}
			tree = t
			pkg = path[len(tpath):]
			return
		}
		err = fmt.Errorf("path %q not inside a GOPATH", path)
		return
	}
	tree = defaultTree
	pkg = path
	for _, t := range Path {
		if t.HasSrc(pkg) {
			tree = t
			return
		}
	}
	if tree == nil {
		err = ErrTreeNotFound
	} else {
		err = ErrNotFound
	}
	return
}

// isLocalPath returns whether the given path is local (/foo ./foo ../foo . ..)
// Windows paths that starts with drive letter (c:\foo c:foo) are considered local.
func isLocalPath(s string) bool {
	const sep = string(filepath.Separator)
	return s == "." || s == ".." ||
		filepath.HasPrefix(s, sep) ||
		filepath.HasPrefix(s, "."+sep) || filepath.HasPrefix(s, ".."+sep) ||
		filepath.VolumeName(s) != ""
}

var (
	// argument lists used by the build's gc and ld methods
	gcImportArgs []string
	ldImportArgs []string

	// default tree for remote packages
	defaultTree *Tree
)

// set up Path: parse and validate GOROOT and GOPATH variables
func init() {
	root := runtime.GOROOT()
	t, err := newTree(root)
	if err != nil {
		log.Printf("invalid GOROOT %q: %v", root, err)
	} else {
		t.Goroot = true
		Path = []*Tree{t}
	}

	for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
		if p == "" {
			continue
		}
		t, err := newTree(p)
		if err != nil {
			log.Printf("invalid GOPATH %q: %v", p, err)
			continue
		}
		Path = append(Path, t)
		gcImportArgs = append(gcImportArgs, "-I", t.PkgDir())
		ldImportArgs = append(ldImportArgs, "-L", t.PkgDir())

		// select first GOPATH entry as default
		if defaultTree == nil {
			defaultTree = t
		}
	}

	// use GOROOT if no valid GOPATH specified
	if defaultTree == nil && len(Path) > 0 {
		defaultTree = Path[0]
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go 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 net

import (
	"testing"
)

type portTest struct {
	netw string
	name string
	port int
	ok   bool
}

var porttests = []portTest{
	portTest{"tcp", "echo", 7, true},
	portTest{"tcp", "discard", 9, true},
	portTest{"tcp", "systat", 11, true},
	portTest{"tcp", "daytime", 13, true},
	portTest{"tcp", "chargen", 19, true},
	portTest{"tcp", "ftp-data", 20, true},
	portTest{"tcp", "ftp", 21, true},
	portTest{"tcp", "ssh", 22, true},
	portTest{"tcp", "telnet", 23, true},
	portTest{"tcp", "smtp", 25, true},
	portTest{"tcp", "time", 37, true},
	portTest{"tcp", "domain", 53, true},
	portTest{"tcp", "gopher", 70, true},
	portTest{"tcp", "finger", 79, true},
	portTest{"tcp", "http", 80, true},

	portTest{"udp", "echo", 7, true},
	portTest{"udp", "tacacs", 49, true},
	portTest{"udp", "tftp", 69, true},
	portTest{"udp", "bootpc", 68, true},
	portTest{"udp", "bootps", 67, true},
	portTest{"udp", "domain", 53, true},
	portTest{"udp", "ntp", 123, true},
	portTest{"udp", "snmp", 161, true},
	portTest{"udp", "syslog", 514, true},
	portTest{"udp", "nfs", 2049, true},

	portTest{"--badnet--", "zzz", 0, false},
	portTest{"tcp", "--badport--", 0, false},
}

func TestLookupPort(t *testing.T) {
	for i := 0; i < len(porttests); i++ {
		tt := porttests[i]
		if port, err := LookupPort(tt.netw, tt.name); port != tt.port || (err == nil) != tt.ok {
			t.Errorf("LookupPort(%q, %q) = %v, %s; want %v",
				tt.netw, tt.name, port, err, tt.port)
		}
	}
}
<commit_msg>net: drop non-RHEL-4.6 ports from test<commit_after>// Copyright 2009 The Go 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 net

import (
	"testing"
)

type portTest struct {
	netw string
	name string
	port int
	ok   bool
}

var porttests = []portTest{
	portTest{"tcp", "echo", 7, true},
	portTest{"tcp", "discard", 9, true},
	portTest{"tcp", "systat", 11, true},
	portTest{"tcp", "daytime", 13, true},
	portTest{"tcp", "chargen", 19, true},
	portTest{"tcp", "ftp-data", 20, true},
	portTest{"tcp", "ftp", 21, true},
	portTest{"tcp", "ssh", 22, true},
	portTest{"tcp", "telnet", 23, true},
	portTest{"tcp", "smtp", 25, true},
	portTest{"tcp", "time", 37, true},
	portTest{"tcp", "domain", 53, true},
	portTest{"tcp", "gopher", 70, true},
	portTest{"tcp", "finger", 79, true},
	portTest{"tcp", "http", 80, true},

	portTest{"udp", "echo", 7, true},
	portTest{"udp", "tftp", 69, true},
	portTest{"udp", "bootpc", 68, true},
	portTest{"udp", "bootps", 67, true},
	portTest{"udp", "domain", 53, true},
	portTest{"udp", "ntp", 123, true},
	portTest{"udp", "snmp", 161, true},
	portTest{"udp", "syslog", 514, true},

	portTest{"--badnet--", "zzz", 0, false},
	portTest{"tcp", "--badport--", 0, false},
}

func TestLookupPort(t *testing.T) {
	for i := 0; i < len(porttests); i++ {
		tt := porttests[i]
		if port, err := LookupPort(tt.netw, tt.name); port != tt.port || (err == nil) != tt.ok {
			t.Errorf("LookupPort(%q, %q) = %v, %s; want %v",
				tt.netw, tt.name, port, err, tt.port)
		}
	}
}
<|endoftext|>