<commit_before>// Copyright 2015 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.

// Grepdiff greps diffs.
//
// Usage:
//
//	grepdiff regexp [file.diff ...]
//
// Grepdiff reads diffs from the named files (or standard input)
// and prints a reduced diff containing only the hunks matching
// the regular expression.
//
// The regular expression syntax is that of the Go regexp package,
// which matches RE2 and roughly matches PCRE, Perl, and most
// other languages.
// For details, see ``go doc regexp/syntax'' or https://godoc.org/regexp/syntax.
//
// The diffs are expected to be in roughly unified diff format,
// as produced by commands like ``git diff'' or ``hg diff''.
//
// Grepdiff exits with status 0 if it found any matches, 1 if it found no matches, and 2 if an error occurred.
//
// Example
//
// To diff two Git revisions and extract just the hunks mentioning foo:
//
//	git diff rev1 rev2 | grepdiff foo
//
// If you are feeling particularly adventurous, to apply those changes:
//
//	git diff rev1 rev2 | grepdiff foo | git apply
//
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: grepdiff regexp [file.diff ...]\n")
	// fmt.Fprintf(os.Stderr, "options:\n")
	// flag.PrintDefaults()
	os.Exit(2)
}

var exitStatus = 1

func main() {
	log.SetFlags(0)
	log.SetPrefix("grepdiff: ")
	flag.Usage = usage
	flag.Parse()
	if flag.NArg() < 1 {
		usage()
	}

	re, err := regexp.Compile(flag.Arg(0))
	if err != nil {
		log.Fatal(err)
	}

	files := flag.Args()[1:]
	if len(files) == 0 {
		grepDiff(re, os.Stdin)
	} else {
		for _, file := range files {
			f, err := os.Open(file)
			if err != nil {
				log.Print(err)
				exitStatus = 2
				continue
			}
			grepDiff(re, f)
			f.Close()
		}
	}

	os.Exit(exitStatus)
}

func grepDiff(re *regexp.Regexp, file *os.File) {
	data, err := ioutil.ReadAll(file)
	grepDiffData(re, data, file.Name())
	if err != nil {
		log.Print("%v", err)
		exitStatus = 2
	}
}

var (
	diffLine = []byte("\ndiff ")
	hunkLine = []byte("\n@@ ")
)

func grepDiffData(re *regexp.Regexp, data []byte, name string) {
	forEach(data, "diff ", func(diff []byte) {
		var hdr []byte
		forEach(diff, "@@ ", func(hunk []byte) {
			if hdr == nil {
				hdr = diff[:cap(diff)-cap(hunk)]
			}
			if re.Match(hunk) {
				os.Stdout.Write(hdr)
				hdr = hdr[:0] // not nil
				os.Stdout.Write(hunk)
				if exitStatus == 1 {
					exitStatus = 0
				}
			}
		})
	})
}

func forEach(x []byte, prefix string, f func([]byte)) {
	b := []byte("\n" + prefix)
	start := 0
	if !bytes.HasPrefix(x, b[1:]) {
		start = bytes.Index(x, b) + 1
		if start == 0 {
			return
		}
	}
	for start < len(x) {
		i := bytes.Index(x[start:], b) + start + 1
		if i == start {
			i = len(x)
		}
		if start >= 0 {
			f(x[start:i])
		}
		start = i
	}
}
<commit_msg>grepdiff: enable multiline mode by default, revise docs<commit_after>// Copyright 2015 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.

// Grepdiff greps diffs.
//
// Usage:
//
//	grepdiff regexp [file.diff ...]
//
// Grepdiff reads diffs from the named files (or standard input)
// and prints a reduced diff containing only the hunks matching
// the regular expression.
//
// The diffs are expected to be in unified diff format,
// as produced by commands like ``git diff'' or ``hg diff''.
//
// The regular expression syntax is that of the Go regexp package,
// which matches RE2 and roughly matches PCRE, Perl, and most
// other languages.
// For details, see ``go doc regexp/syntax'' or https://godoc.org/regexp/syntax.
//
// Unlike grep, the regexp search considers the entire hunk
// starting with the @@ line, not individual lines.
// It is therefore possible to search for multiline matches.
// As a nod to grep, however, the regexp search enables the (?m) flag
// by default, so that ^ and $ match the start and end of each line,
// not just the start and end of the hunk.
// (To disable this, start the regexp passed to grepdiff with (?-m).)
//
// Grepdiff exits with status 0 if it found any matches, 1 if it found no matches, and 2 if an error occurred.
//
// Examples
//
// Diff two Git revisions and extract just the hunks mentioning foo:
//
//	git diff rev1 rev2 | grepdiff foo
//
// For the adventurous, apply those changes:
//
//	git diff rev1 rev2 | grepdiff foo | git apply
//
// Extract changes in func New:
//
//	git diff rev1 HEAD | grepdiff ' @@ func New\('
//
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: grepdiff regexp [file.diff ...]\n")
	// fmt.Fprintf(os.Stderr, "options:\n")
	// flag.PrintDefaults()
	os.Exit(2)
}

var exitStatus = 1

func main() {
	log.SetFlags(0)
	log.SetPrefix("grepdiff: ")
	flag.Usage = usage
	flag.Parse()
	if flag.NArg() < 1 {
		usage()
	}

	reStr := flag.Arg(0)
	files := flag.Args()[1:]

	// Compile regexp twice: once unmodified for reporting errors,
	// and again with (?m) for real use. If somehow the (?m) does cause
	// a problem, handle it gracefully.
	re, err := regexp.Compile(reStr)
	if err != nil {
		log.Fatal(err)
	}
	re, err = regexp.Compile("(?m)" + reStr)
	if err != nil {
		log.Fatal(err)
	}

	if len(files) == 0 {
		grepDiff(re, os.Stdin)
	} else {
		for _, file := range files {
			f, err := os.Open(file)
			if err != nil {
				log.Print(err)
				exitStatus = 2
				continue
			}
			grepDiff(re, f)
			f.Close()
		}
	}

	os.Exit(exitStatus)
}

func grepDiff(re *regexp.Regexp, file *os.File) {
	data, err := ioutil.ReadAll(file)
	grepDiffData(re, data, file.Name())
	if err != nil {
		log.Print("%v", err)
		exitStatus = 2
	}
}

var (
	diffLine = []byte("\ndiff ")
	hunkLine = []byte("\n@@ ")
)

func grepDiffData(re *regexp.Regexp, data []byte, name string) {
	forEach(data, "diff ", func(diff []byte) {
		var hdr []byte
		forEach(diff, "@@ ", func(hunk []byte) {
			if hdr == nil {
				hdr = diff[:cap(diff)-cap(hunk)]
			}
			if re.Match(hunk) {
				os.Stdout.Write(hdr)
				hdr = hdr[:0] // not nil
				os.Stdout.Write(hunk)
				if exitStatus == 1 {
					exitStatus = 0
				}
			}
		})
	})
}

func forEach(x []byte, prefix string, f func([]byte)) {
	b := []byte("\n" + prefix)
	start := 0
	if !bytes.HasPrefix(x, b[1:]) {
		start = bytes.Index(x, b) + 1
		if start == 0 {
			return
		}
	}
	for start < len(x) {
		i := bytes.Index(x[start:], b) + start + 1
		if i == start {
			i = len(x)
		}
		if start >= 0 {
			f(x[start:i])
		}
		start = i
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"
	"strings"
)

func main() {
	flag.Parse()

	args := flag.Args()

	currentDirectory, _ := os.Getwd()

	if len(args) < 2 {
		speak("error> missing inventory", true)
	}

	if len(args) == 2 {
		os.Args = append(os.Args, "ls")
	}

	passThrough := ""
	if len(args) >= 3 {
		passThrough = strings.Join(args[3:], " ")
	}

	newMarvin(marvinFile(".", "marvin.yml"), currentDirectory, os.Args[1], os.Args[2], passThrough)
}
<commit_msg>fixed passthrough/args<commit_after>package main

import (
	"flag"
	"os"
	"strings"
)

func main() {
	flag.Parse()

	args := flag.Args()

	currentDirectory, _ := os.Getwd()

	if len(args) < 2 {
		speak("error> missing inventory", true)
	}

	if len(args) == 2 {
		os.Args = append(os.Args, "ls")
	}

	passThrough := ""
	if len(args) >= 3 {
		passThrough = strings.Join(args[2:], " ")
	}
	newMarvin(marvinFile(".", "marvin.yml"), currentDirectory, os.Args[1], os.Args[2], passThrough)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/rancher/convoy/api"
	"github.com/rancher/convoy/client"
	"os"
)

const (
	// version of Convoy
	VERSION = "0.4.3"
)

func cleanup() {
	if r := recover(); r != nil {
		api.ResponseLogAndError(r)
		os.Exit(1)
	}
}

func main() {
	defer cleanup()

	cli := client.NewCli(VERSION)
	err := cli.Run(os.Args)
	if err != nil {
		panic(fmt.Errorf("Error when executing command: %v", err))
	}
}
<commit_msg>Update Convoy version to 0.4.4-dev<commit_after>package main

import (
	"fmt"
	"github.com/rancher/convoy/api"
	"github.com/rancher/convoy/client"
	"os"
)

const (
	// version of Convoy
	VERSION = "0.4.4-dev"
)

func cleanup() {
	if r := recover(); r != nil {
		api.ResponseLogAndError(r)
		os.Exit(1)
	}
}

func main() {
	defer cleanup()

	cli := client.NewCli(VERSION)
	err := cli.Run(os.Args)
	if err != nil {
		panic(fmt.Errorf("Error when executing command: %v", err))
	}
}
<|endoftext|>


<commit_before>package main

import "fmt"

import "github.com/jessevdk/go-flags"
import "github.com/tj/go-debug"
import "github.com/peterh/liner"

func main() {
	var opts struct {
		ConfigFile string `short:"c" long:"config" description:"Path to config file"`
	}

	debug := debug.Debug("oktad:main")
	args, err := flags.Parse(&opts)

	if err != nil {
		return
	}

	debug("loading configuration data")
	// try to load configuration
	oktaCfg, err := parseConfig(opts.ConfigFile)

	if err != nil {
		fmt.Println("Error reading config file!")
		debug("cfg read err: %s", err)
		return
	}

	if len(args) <= 0 {
		fmt.Println("You must supply a profile name, sorry.")
		return
	}

	if err != nil {
		fmt.Println("Error reading AWS configuration!")
		return
	}

	user, pass, err := readUserPass()
	if err != nil {
		// if we got an error here, the user bailed on us
		debug("control-c caught in liner, probably")
		return
	}

	if user == "" || pass == "" {
		fmt.Println("Must supply a username and password!")
		return
	}

	ores, err := login(oktaCfg, user, pass)
	if err != nil {
		fmt.Println("Error grabbing temporary credentials!")
		debug("login err %s", err)
		return
	}

	if ores.Status == "MFA_REQUIRED" {
		factor, err := extractTokenFactor(ores)

		if err != nil {
			fmt.Println("Error processing okta response!")
			debug("err from extractTokenFactor was %s", err)
			return
		}

		mfaToken, err := readMfaToken()
		if err != nil {
			debug("control-c caught in liner, probably")
			return
		}

		sessionToken, err := doMfa(ores, factor, mfaToken)
		if err != nil {
			fmt.Println("Error performing MFA auth!")
			debug("error from doMfa was %s", err)
			return
		}

		saml, err := getSaml(oktaCfg, sessionToken)
		debug("got saml: \n%s", saml.raw)

		if err != nil {
			fmt.Println("Error preparing to AssumeRole!")
			debug("getSaml err was %s", err)
			return
		}

		acfg, err := readAwsProfile(
			fmt.Sprintf("profile %s", args[0]),
		)

		if err != nil {
			fmt.Println("Error reading your AWS profile!")
			debug("error was... %s", err)
		}

		mainCreds, err := assumeFirstRole(acfg, saml)
		if err != nil {
			fmt.Println("Error assuming first role!")
			debug("error was %s", err)
			return
		}

		finalCreds, err := assumeDestinationRole(acfg, mainCreds)
		if err != nil {
			fmt.Println("Error assuming second role!")
			debug("error was %s", err)
			return
		}

		// WHOA!
		var cmd string
		var cArgs []string

		if len(args) < 2 {
			fmt.Println("No program specified!")
			return
		}

		for i, a := range args[1:] {
			if a != "--" {
				cmd = a
				if len(args) > (i + 2) {
					cArgs = args[i+1:]
				} else {
					cArgs = []string{}
				}
				break
			}
		}

		fmt.Println(launch(cmd, cArgs, finalCreds))

	} else {
		fmt.Println("MFA required to use this tool.")
	}
}

// reads the username and password from the command line
// returns user, then pass, then an error
func readUserPass() (user string, pass string, err error) {
	li := liner.NewLiner()

	// remember to close or weird stuff happens
	defer li.Close()

	li.SetCtrlCAborts(true)
	user, err = li.Prompt("Username: ")
	if err != nil {
		return
	}

	pass, err = li.PasswordPrompt("Password: ")
	if err != nil {
		return
	}

	return
}

// reads and returns an mfa token
func readMfaToken() (string, error) {
	li := liner.NewLiner()
	defer li.Close()
	li.SetCtrlCAborts(true)
	fmt.Println("Your account requires MFA; please enter a token.")
	return li.Prompt("MFA token: ")
}
<commit_msg>only show exec output in debug; fix support for double-dash<commit_after>package main

import "fmt"

import "github.com/jessevdk/go-flags"
import "github.com/tj/go-debug"
import "github.com/peterh/liner"

func main() {
	var opts struct {
		ConfigFile string `short:"c" long:"config" description:"Path to config file"`
	}

	debug := debug.Debug("oktad:main")
	args, err := flags.Parse(&opts)

	if err != nil {
		return
	}

	debug("loading configuration data")
	// try to load configuration
	oktaCfg, err := parseConfig(opts.ConfigFile)

	if err != nil {
		fmt.Println("Error reading config file!")
		debug("cfg read err: %s", err)
		return
	}

	if len(args) <= 0 {
		fmt.Println("You must supply a profile name, sorry.")
		return
	}

	if err != nil {
		fmt.Println("Error reading AWS configuration!")
		return
	}

	user, pass, err := readUserPass()
	if err != nil {
		// if we got an error here, the user bailed on us
		debug("control-c caught in liner, probably")
		return
	}

	if user == "" || pass == "" {
		fmt.Println("Must supply a username and password!")
		return
	}

	ores, err := login(oktaCfg, user, pass)
	if err != nil {
		fmt.Println("Error grabbing temporary credentials!")
		debug("login err %s", err)
		return
	}

	if ores.Status == "MFA_REQUIRED" {
		factor, err := extractTokenFactor(ores)

		if err != nil {
			fmt.Println("Error processing okta response!")
			debug("err from extractTokenFactor was %s", err)
			return
		}

		mfaToken, err := readMfaToken()
		if err != nil {
			debug("control-c caught in liner, probably")
			return
		}

		sessionToken, err := doMfa(ores, factor, mfaToken)
		if err != nil {
			fmt.Println("Error performing MFA auth!")
			debug("error from doMfa was %s", err)
			return
		}

		saml, err := getSaml(oktaCfg, sessionToken)
		debug("got saml: \n%s", saml.raw)

		if err != nil {
			fmt.Println("Error preparing to AssumeRole!")
			debug("getSaml err was %s", err)
			return
		}

		acfg, err := readAwsProfile(
			fmt.Sprintf("profile %s", args[0]),
		)

		if err != nil {
			fmt.Println("Error reading your AWS profile!")
			debug("error was... %s", err)
		}

		mainCreds, err := assumeFirstRole(acfg, saml)
		if err != nil {
			fmt.Println("Error assuming first role!")
			debug("error was %s", err)
			return
		}

		finalCreds, err := assumeDestinationRole(acfg, mainCreds)
		if err != nil {
			fmt.Println("Error assuming second role!")
			debug("error was %s", err)
			return
		}

		// WHOA!
		var cmd string
		var cArgs []string

		if len(args) < 2 {
			fmt.Println("No program specified!")
			return
		}

		for i, a := range args[1:] {
			if a != "--" {
				cmd = a
				if len(args) > (i + 2) {
					cArgs = args[i+2:]
				} else {
					cArgs = []string{}
				}
				break
			}
		}

		err = launch(cmd, cArgs, finalCreds)
		if err != nil {
			debug("caught error from launcher, %s", err)
		}

	} else {
		fmt.Println("MFA required to use this tool.")
	}
}

// reads the username and password from the command line
// returns user, then pass, then an error
func readUserPass() (user string, pass string, err error) {
	li := liner.NewLiner()

	// remember to close or weird stuff happens
	defer li.Close()

	li.SetCtrlCAborts(true)
	user, err = li.Prompt("Username: ")
	if err != nil {
		return
	}

	pass, err = li.PasswordPrompt("Password: ")
	if err != nil {
		return
	}

	return
}

// reads and returns an mfa token
func readMfaToken() (string, error) {
	li := liner.NewLiner()
	defer li.Close()
	li.SetCtrlCAborts(true)
	fmt.Println("Your account requires MFA; please enter a token.")
	return li.Prompt("MFA token: ")
}
<|endoftext|>


<commit_before>//the icws_golib package wraps CIC ICWS fuctionality in a GO library.
//To get started, call icws_golib.NewIcws() to instansiate a new Icws
//struct.  Then call icws.Login(...) and continue on from there.
package icws_golib

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
)

type Icws struct {
	CurrentToken, CurrentCookie, CurrentSession, CurrentServer, UserId, HttpScheme string
	Port                                                                           int
}

//Version information for the server
type ServerVersion struct {
	//The product's two-digit release year. For the release "CIC 2015 R1" this value will be "15"
	MajorVersion string
	//The product's release number. For the release "CIC 2015 R1" this value will be "1".
	MinorVersion string
	//The patch number of the release. The value "0" indicates the release without any patches. For the release "CIC 2015 R1" this value will be "0", and for the release "CIC 2015 R1 Patch2" this value will be "2".
	Su string
	//The product line identifier.
	ProductId string
	//The codebase identifier.
	CodeBaseId string
	//The build number.
	Build string
	//The display string for the release. This does not include patch information.
	ProductReleaseDisplayString string
	//The display string for the release including patch information. This string is recommended for use on application "About" screens.
	ProductPatchDisplayString string
}

//Definition of a server feature
type ServerFeature struct {
	//Id of the features
	FeatureId string
	//version of the feature
	Version int
}

//Creates a new ICWS struct
func NewIcws() (icws *Icws) {
	icws = &Icws{}
	icws.HttpScheme = "https"
	icws.Port = 8019
	return
}

func (i *Icws) loginWithData(applicationName, server, username, password string, loginData map[string]string) (err error) {

	urlFormat := "%s://%s:%d"
	server = fmt.Sprintf(urlFormat, i.HttpScheme, server, i.Port)

	log.Printf("Logging into %s with user %s", server, username)

	i.CurrentSession = ""
	i.CurrentServer = server
	body, statusCode, err, cookie := i.httpPostAdvanced("connection", loginData)

	nextServerIndex := 0
	for statusCode == 503 {

		var returnData map[string]interface{}
		json.Unmarshal(body, &returnData)

		nextServer := returnData["alternateHostList"].([]interface{})[0]

		server = fmt.Sprintf(urlFormat, nextServer)

		log.Printf("Redirected to server %s", server)

		i.CurrentServer = server
		body, statusCode, err, cookie = i.httpPostAdvanced("connection", loginData)

		nextServerIndex++
	}

	if err == nil {

		var returnData map[string]string
		json.Unmarshal(body, &returnData)
		i.CurrentToken = returnData["csrfToken"]
		i.CurrentSession = returnData["sessionId"]
		i.CurrentServer = server
		i.CurrentCookie = cookie
		i.UserId = username

	} else {
		log.Printf("ERROR: %s\n", err.Error())
	}
	return
}

//logs into CIC through a reverse proxy
func (i *Icws) ProxyLoginWithData(applicationName, proxyUrl, serverName, username, password string, loginData map[string]string) (err error) {

	urlFormat := "%s/%s"
	server := fmt.Sprintf(urlFormat, proxyUrl, serverName)

	log.Printf("Logging into %s with user %s", server, username)

	i.CurrentSession = ""
	i.CurrentServer = server
	body, statusCode, err, cookie := i.httpPostAdvanced("connection", loginData)

	if err != nil {
		log.Printf("ERROR: %s\n", err.Error())
		return
	}

	nextServerIndex := 0
	for statusCode == 503 {

		var returnData map[string]interface{}
		json.Unmarshal(body, &returnData)

		if returnData["alternateHostList"] == nil {
			err = errors.New("Unable to connect to server, unknown error")
		}

		nextServer := returnData["alternateHostList"].([]interface{})[0]

		server = fmt.Sprintf(urlFormat, proxyUrl, nextServer)

		log.Printf("Redirected to server %s", server)

		i.CurrentServer = server
		body, statusCode, err, cookie = i.httpPostAdvanced("connection", loginData)

		nextServerIndex++
	}

	if err == nil {

		var returnData map[string]string
		json.Unmarshal(body, &returnData)
		i.CurrentToken = returnData["csrfToken"]
		i.CurrentSession = returnData["sessionId"]
		i.CurrentServer = server
		i.CurrentCookie = cookie
		i.UserId = username

	} else {
		log.Printf("ERROR: %s\n", err.Error())
	}
	return
}

//logs into a CIC server through a reverse proxy where the url to reach the server would be proxyUrl/serverName
func (i *Icws) ProxyLogin(applicationName, proxyUrl, serverName, username, password string) (err error) {

	var loginData = map[string]string{
		"__type":          "urn:inin.com:connection:icAuthConnectionRequestSettings",
		"applicationName": applicationName,
		"userID":          username,
		"password":        password,
	}

	return i.ProxyLoginWithData(applicationName, proxyUrl, serverName, username, password, loginData)
}

//Logs into a CIC server for a MarketPlace application using the app's custom license.  Server should be a url e.g. https://MyServer:8019
func (i *Icws) ProxyLoginMarketPlaceApp(applicationName, proxyUrl, serverName, username, password, marketplaceLicense, marketplaceAppKey string) (err error) {

	var loginData = map[string]string{
		"__type":                            "urn:inin.com:connection:icAuthConnectionRequestSettings",
		"applicationName":                   applicationName,
		"userID":                            username,
		"password":                          password,
		"marketPlaceApplicationLicenseName": marketplaceLicense,
		"marketPlaceApplicationCode":        marketplaceAppKey,
	}

	return i.ProxyLoginWithData(applicationName, proxyUrl, serverName, username, password, loginData)
}

//Logs into a CIC server.  Server should be a server name e.g. MyServer.domain.com
func (i *Icws) Login(applicationName, server, username, password string) (err error) {

	var loginData = map[string]string{
		"__type":          "urn:inin.com:connection:icAuthConnectionRequestSettings",
		"applicationName": applicationName,
		"userID":          username,
		"password":        password,
	}

	return i.loginWithData(applicationName, server, username, password, loginData)
}

//Logs into a CIC server for a MarketPlace application using the app's custom license.  Server should be a url e.g. https://MyServer:8019
func (i *Icws) LoginMarketPlaceApp(applicationName, server, username, password, marketplaceLicense, marketplaceAppKey string) (err error) {

	var loginData = map[string]string{
		"__type":                            "urn:inin.com:connection:icAuthConnectionRequestSettings",
		"applicationName":                   applicationName,
		"userID":                            username,
		"password":                          password,
		"marketPlaceApplicationLicenseName": marketplaceLicense,
		"marketPlaceApplicationCode":        marketplaceAppKey,
	}

	return i.loginWithData(applicationName, server, username, password, loginData)
}

//gets server version details.  Does not need to be connected to the server
func (i *Icws) GetVersion() (version ServerVersion, err error) {

	body, err := i.httpNoConnectionGet("/connection/version")

	err = json.Unmarshal(body, &version)

	return
}

//Gets a list of features and their version from the server
func (i *Icws) GetFeatures() (features []ServerFeature, err error) {

	body, err := i.httpNoConnectionGet("/connection/features")

	if err != nil {
		return nil, err
	}

	var featureMap map[string][]ServerFeature
	err = json.Unmarshal(body, &featureMap)

	features = featureMap["featureInfoList"]
	return

}

func (i *Icws) httpDelete(url string) (err error) {

	req, err := i.httpRequest("DELETE", url, nil)

	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return
	}
	defer response.Body.Close()
	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, _ := ioutil.ReadAll(response.Body)
	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	return
}

func (i *Icws) httpGet(url string) (body []byte, err error) {

	req, err := i.httpRequest("GET", url, nil)

	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return
	}
	defer response.Body.Close()
	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, err = ioutil.ReadAll(response.Body)
	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	return
}

func (i *Icws) httpNoConnectionGet(url string) (body []byte, err error) {

	req, err := i.httpNoConnectionRequest("GET", url, nil)

	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return
	}
	defer response.Body.Close()
	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, err = ioutil.ReadAll(response.Body)
	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	return
}

func (i *Icws) httpPost(url string, attrs map[string]string) (body []byte, err error) {
	body, _, err, _ = i.httpPostAdvanced(url, attrs)
	return
}

func (i *Icws) httpPostAdvanced(url string, attrs map[string]string) (body []byte, statusCode int, err error, cookie string) {

	rbody, _ := json.Marshal(attrs)
	req, err := i.httpRequest("POST", url, bytes.NewReader(rbody))
	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return

	}
	defer response.Body.Close()

	statusCode = response.StatusCode

	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, err = ioutil.ReadAll(response.Body)

	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	if response.Header["Set-Cookie"] != nil {
		cookie = response.Header["Set-Cookie"][0]
	}
	return
}

func (i *Icws) httpPut(url string, attrs map[string]string) (body []byte, err error) {

	rbody, _ := json.Marshal(attrs)
	req, err := i.httpRequest("PUT", url, bytes.NewReader(rbody))
	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return

	}
	defer response.Body.Close()
	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, err = ioutil.ReadAll(response.Body)

	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	return
}

func (i *Icws) httpClient() (client *http.Client) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client = &http.Client{Transport: tr}
	return
}

func (i *Icws) httpNoConnectionRequest(method, url string, body io.Reader) (request *http.Request, err error) {
	request, err = http.NewRequest(method, i.CurrentServer+"/icws"+url, body)
	if err != nil {
		return
	}

	request.Header.Add("Content-Type", "application/json")
	request.Header.Add("Accept-Language", "en-us")

	return
}

func (i *Icws) httpRequest(method, url string, body io.Reader) (request *http.Request, err error) {
	request, err = http.NewRequest(method, i.CurrentServer+"/icws/"+i.CurrentSession+url, body)
	if err != nil {
		return
	}

	request.Header.Add("Content-Type", "application/json")
	request.Header.Add("Accept-Language", "en-us")

	if len(i.CurrentCookie) > 0 {
		request.Header.Add("Cookie", i.CurrentCookie)
	} else {
		return
	}

	if len(i.CurrentToken) > 0 {
		request.Header.Add("ININ-ICWS-CSRF-Token", i.CurrentToken)
	} else {
		return
	}

	// request.Header.Add("User-Agent", fmt.Sprintf("cic cli (%s-%s)", runtime.GOOS, runtime.GOARCH))
	return
}

func createErrorMessage(statusCode int, body []byte) string {

	var errorDescription string

	switch statusCode {
	case 400:
		errorDescription = "Bad Request (400)"
	case 401:
		errorDescription = "Unauthorized (401)"
	case 403:
		errorDescription = "Forbidden (403)"
	case 404:
		errorDescription = "Not Found (404)"
	case 410:
		errorDescription = "Gone (410)"
	case 500:
		errorDescription = "Internal Server Error (500)"
	}

	var message map[string]interface{}
	json.Unmarshal(body, &message)

	if message["errorId"] != nil {
		errorDescription += ": " + message["errorId"].(string)
	}

	if message["message"] != nil {
		errorDescription += " " + message["message"].(string)
	}
	return errorDescription
}
<commit_msg>removing error check that is valid for a redirect<commit_after>//the icws_golib package wraps CIC ICWS fuctionality in a GO library.
//To get started, call icws_golib.NewIcws() to instansiate a new Icws
//struct.  Then call icws.Login(...) and continue on from there.
package icws_golib

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
)

type Icws struct {
	CurrentToken, CurrentCookie, CurrentSession, CurrentServer, UserId, HttpScheme string
	Port                                                                           int
}

//Version information for the server
type ServerVersion struct {
	//The product's two-digit release year. For the release "CIC 2015 R1" this value will be "15"
	MajorVersion string
	//The product's release number. For the release "CIC 2015 R1" this value will be "1".
	MinorVersion string
	//The patch number of the release. The value "0" indicates the release without any patches. For the release "CIC 2015 R1" this value will be "0", and for the release "CIC 2015 R1 Patch2" this value will be "2".
	Su string
	//The product line identifier.
	ProductId string
	//The codebase identifier.
	CodeBaseId string
	//The build number.
	Build string
	//The display string for the release. This does not include patch information.
	ProductReleaseDisplayString string
	//The display string for the release including patch information. This string is recommended for use on application "About" screens.
	ProductPatchDisplayString string
}

//Definition of a server feature
type ServerFeature struct {
	//Id of the features
	FeatureId string
	//version of the feature
	Version int
}

//Creates a new ICWS struct
func NewIcws() (icws *Icws) {
	icws = &Icws{}
	icws.HttpScheme = "https"
	icws.Port = 8019
	return
}

func (i *Icws) loginWithData(applicationName, server, username, password string, loginData map[string]string) (err error) {

	urlFormat := "%s://%s:%d"
	server = fmt.Sprintf(urlFormat, i.HttpScheme, server, i.Port)

	log.Printf("Logging into %s with user %s", server, username)

	i.CurrentSession = ""
	i.CurrentServer = server
	body, statusCode, err, cookie := i.httpPostAdvanced("connection", loginData)

	nextServerIndex := 0
	for statusCode == 503 {

		var returnData map[string]interface{}
		json.Unmarshal(body, &returnData)

		nextServer := returnData["alternateHostList"].([]interface{})[0]

		server = fmt.Sprintf(urlFormat, nextServer)

		log.Printf("Redirected to server %s", server)

		i.CurrentServer = server
		body, statusCode, err, cookie = i.httpPostAdvanced("connection", loginData)

		nextServerIndex++
	}

	if err == nil {

		var returnData map[string]string
		json.Unmarshal(body, &returnData)
		i.CurrentToken = returnData["csrfToken"]
		i.CurrentSession = returnData["sessionId"]
		i.CurrentServer = server
		i.CurrentCookie = cookie
		i.UserId = username

	} else {
		log.Printf("ERROR: %s\n", err.Error())
	}
	return
}

//logs into CIC through a reverse proxy
func (i *Icws) ProxyLoginWithData(applicationName, proxyUrl, serverName, username, password string, loginData map[string]string) (err error) {

	urlFormat := "%s/%s"
	server := fmt.Sprintf(urlFormat, proxyUrl, serverName)

	log.Printf("Logging into %s with user %s", server, username)

	i.CurrentSession = ""
	i.CurrentServer = server
	body, statusCode, err, cookie := i.httpPostAdvanced("connection", loginData)

	nextServerIndex := 0
	for statusCode == 503 {

		var returnData map[string]interface{}
		json.Unmarshal(body, &returnData)

		if returnData["alternateHostList"] == nil {
			err = errors.New("Unable to connect to server, unknown error")
		}

		nextServer := returnData["alternateHostList"].([]interface{})[0]

		server = fmt.Sprintf(urlFormat, proxyUrl, nextServer)

		log.Printf("Redirected to server %s", server)

		i.CurrentServer = server
		body, statusCode, err, cookie = i.httpPostAdvanced("connection", loginData)

		nextServerIndex++
	}

	if err == nil {

		var returnData map[string]string
		json.Unmarshal(body, &returnData)
		i.CurrentToken = returnData["csrfToken"]
		i.CurrentSession = returnData["sessionId"]
		i.CurrentServer = server
		i.CurrentCookie = cookie
		i.UserId = username

	} else {
		log.Printf("ERROR: %s\n", err.Error())
	}
	return
}

//logs into a CIC server through a reverse proxy where the url to reach the server would be proxyUrl/serverName
func (i *Icws) ProxyLogin(applicationName, proxyUrl, serverName, username, password string) (err error) {

	var loginData = map[string]string{
		"__type":          "urn:inin.com:connection:icAuthConnectionRequestSettings",
		"applicationName": applicationName,
		"userID":          username,
		"password":        password,
	}

	return i.ProxyLoginWithData(applicationName, proxyUrl, serverName, username, password, loginData)
}

//Logs into a CIC server for a MarketPlace application using the app's custom license.  Server should be a url e.g. https://MyServer:8019
func (i *Icws) ProxyLoginMarketPlaceApp(applicationName, proxyUrl, serverName, username, password, marketplaceLicense, marketplaceAppKey string) (err error) {

	var loginData = map[string]string{
		"__type":                            "urn:inin.com:connection:icAuthConnectionRequestSettings",
		"applicationName":                   applicationName,
		"userID":                            username,
		"password":                          password,
		"marketPlaceApplicationLicenseName": marketplaceLicense,
		"marketPlaceApplicationCode":        marketplaceAppKey,
	}

	return i.ProxyLoginWithData(applicationName, proxyUrl, serverName, username, password, loginData)
}

//Logs into a CIC server.  Server should be a server name e.g. MyServer.domain.com
func (i *Icws) Login(applicationName, server, username, password string) (err error) {

	var loginData = map[string]string{
		"__type":          "urn:inin.com:connection:icAuthConnectionRequestSettings",
		"applicationName": applicationName,
		"userID":          username,
		"password":        password,
	}

	return i.loginWithData(applicationName, server, username, password, loginData)
}

//Logs into a CIC server for a MarketPlace application using the app's custom license.  Server should be a url e.g. https://MyServer:8019
func (i *Icws) LoginMarketPlaceApp(applicationName, server, username, password, marketplaceLicense, marketplaceAppKey string) (err error) {

	var loginData = map[string]string{
		"__type":                            "urn:inin.com:connection:icAuthConnectionRequestSettings",
		"applicationName":                   applicationName,
		"userID":                            username,
		"password":                          password,
		"marketPlaceApplicationLicenseName": marketplaceLicense,
		"marketPlaceApplicationCode":        marketplaceAppKey,
	}

	return i.loginWithData(applicationName, server, username, password, loginData)
}

//gets server version details.  Does not need to be connected to the server
func (i *Icws) GetVersion() (version ServerVersion, err error) {

	body, err := i.httpNoConnectionGet("/connection/version")

	err = json.Unmarshal(body, &version)

	return
}

//Gets a list of features and their version from the server
func (i *Icws) GetFeatures() (features []ServerFeature, err error) {

	body, err := i.httpNoConnectionGet("/connection/features")

	if err != nil {
		return nil, err
	}

	var featureMap map[string][]ServerFeature
	err = json.Unmarshal(body, &featureMap)

	features = featureMap["featureInfoList"]
	return

}

func (i *Icws) httpDelete(url string) (err error) {

	req, err := i.httpRequest("DELETE", url, nil)

	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return
	}
	defer response.Body.Close()
	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, _ := ioutil.ReadAll(response.Body)
	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	return
}

func (i *Icws) httpGet(url string) (body []byte, err error) {

	req, err := i.httpRequest("GET", url, nil)

	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return
	}
	defer response.Body.Close()
	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, err = ioutil.ReadAll(response.Body)
	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	return
}

func (i *Icws) httpNoConnectionGet(url string) (body []byte, err error) {

	req, err := i.httpNoConnectionRequest("GET", url, nil)

	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return
	}
	defer response.Body.Close()
	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, err = ioutil.ReadAll(response.Body)
	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	return
}

func (i *Icws) httpPost(url string, attrs map[string]string) (body []byte, err error) {
	body, _, err, _ = i.httpPostAdvanced(url, attrs)
	return
}

func (i *Icws) httpPostAdvanced(url string, attrs map[string]string) (body []byte, statusCode int, err error, cookie string) {

	rbody, _ := json.Marshal(attrs)
	req, err := i.httpRequest("POST", url, bytes.NewReader(rbody))
	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return

	}
	defer response.Body.Close()

	statusCode = response.StatusCode

	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, err = ioutil.ReadAll(response.Body)

	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	if response.Header["Set-Cookie"] != nil {
		cookie = response.Header["Set-Cookie"][0]
	}
	return
}

func (i *Icws) httpPut(url string, attrs map[string]string) (body []byte, err error) {

	rbody, _ := json.Marshal(attrs)
	req, err := i.httpRequest("PUT", url, bytes.NewReader(rbody))
	if err != nil {
		return
	}

	response, err := i.httpClient().Do(req)
	if err != nil {
		return

	}
	defer response.Body.Close()
	if response.StatusCode == 401 {
		err = errors.New("authorization expired")
		return
	}
	body, err = ioutil.ReadAll(response.Body)

	if response.StatusCode/100 != 2 {
		err = errors.New(createErrorMessage(response.StatusCode, body))

		return
	}

	return
}

func (i *Icws) httpClient() (client *http.Client) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client = &http.Client{Transport: tr}
	return
}

func (i *Icws) httpNoConnectionRequest(method, url string, body io.Reader) (request *http.Request, err error) {
	request, err = http.NewRequest(method, i.CurrentServer+"/icws"+url, body)
	if err != nil {
		return
	}

	request.Header.Add("Content-Type", "application/json")
	request.Header.Add("Accept-Language", "en-us")

	return
}

func (i *Icws) httpRequest(method, url string, body io.Reader) (request *http.Request, err error) {
	request, err = http.NewRequest(method, i.CurrentServer+"/icws/"+i.CurrentSession+url, body)
	if err != nil {
		return
	}

	request.Header.Add("Content-Type", "application/json")
	request.Header.Add("Accept-Language", "en-us")

	if len(i.CurrentCookie) > 0 {
		request.Header.Add("Cookie", i.CurrentCookie)
	} else {
		return
	}

	if len(i.CurrentToken) > 0 {
		request.Header.Add("ININ-ICWS-CSRF-Token", i.CurrentToken)
	} else {
		return
	}

	// request.Header.Add("User-Agent", fmt.Sprintf("cic cli (%s-%s)", runtime.GOOS, runtime.GOARCH))
	return
}

func createErrorMessage(statusCode int, body []byte) string {

	var errorDescription string

	switch statusCode {
	case 400:
		errorDescription = "Bad Request (400)"
	case 401:
		errorDescription = "Unauthorized (401)"
	case 403:
		errorDescription = "Forbidden (403)"
	case 404:
		errorDescription = "Not Found (404)"
	case 410:
		errorDescription = "Gone (410)"
	case 500:
		errorDescription = "Internal Server Error (500)"
	}

	var message map[string]interface{}
	json.Unmarshal(body, &message)

	if message["errorId"] != nil {
		errorDescription += ": " + message["errorId"].(string)
	}

	if message["message"] != nil {
		errorDescription += " " + message["message"].(string)
	}
	return errorDescription
}
<|endoftext|>


<commit_before>package main

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

	"github.com/pivotalservices/gtils/osutils"
)

func main() {
	flag.Parse()
	root := flag.Arg(0)
	target := flag.Arg(1)
	fmt.Println(fmt.Sprintf("smashing vendor @%s into %s", root, target))
	err := new(smasher).Run(root, target)
	fmt.Printf("errors returned %v\n", err)
}

type smasher struct {
	root   string
	target string
}

func (s *smasher) Run(root, target string) (err error) {
	s.root = root
	s.target = target
	if err = filepath.Walk(root, s.visit); err == nil {
		err = filepath.Walk(root, s.destroy)
	}
	return err
}

func (s *smasher) destroy(path string, f os.FileInfo, err error) error {
	if filepath.Base(path) == "vendor" {
		fmt.Printf("Hulk Crush: %s\n", path)
		err = os.RemoveAll(path)
	}
	return err
}

func (s *smasher) visit(path string, f os.FileInfo, err error) error {
	if filepath.Base(path) == "vendor" {
		fmt.Printf("Hulk Smash: %s\n", path)
		err = filepath.Walk(path, s.smash)
	}
	return err
}

func (s *smasher) smash(path string, f os.FileInfo, err error) error {
	p := strings.Split(path, "/vendor/")
	ref, _ := os.Stat(path)
	if !ref.IsDir() {
		err = Copy(s.target+p[len(p)-1], path)
	} else {
		os.MkdirAll(path, 0777)
	}
	return err
}

func Copy(dst, src string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := osutils.SafeCreate(dst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, in)
	cerr := out.Close()
	if err != nil {
		return err
	}
	return cerr
}
<commit_msg>packing in so there are no deps<commit_after>package main

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

func main() {
	flag.Parse()
	root := flag.Arg(0)
	target := flag.Arg(1)
	fmt.Println(fmt.Sprintf("smashing vendor @%s into %s", root, target))
	err := new(smasher).Run(root, target)
	fmt.Printf("errors returned %v\n", err)
}

type smasher struct {
	root   string
	target string
}

func (s *smasher) Run(root, target string) (err error) {
	s.root = root
	s.target = target
	if err = filepath.Walk(root, s.visit); err == nil {
		err = filepath.Walk(root, s.destroy)
	}
	return err
}

func (s *smasher) destroy(path string, f os.FileInfo, err error) error {
	if filepath.Base(path) == "vendor" {
		fmt.Printf("Hulk Crush: %s\n", path)
		err = os.RemoveAll(path)
	}
	return err
}

func (s *smasher) visit(path string, f os.FileInfo, err error) error {
	if filepath.Base(path) == "vendor" {
		fmt.Printf("Hulk Smash: %s\n", path)
		err = filepath.Walk(path, s.smash)
	}
	return err
}

func (s *smasher) smash(path string, f os.FileInfo, err error) error {
	p := strings.Split(path, "/vendor/")
	ref, _ := os.Stat(path)
	if !ref.IsDir() {
		err = Copy(s.target+p[len(p)-1], path)
	} else {
		os.MkdirAll(path, 0777)
	}
	return err
}

func Copy(dst, src string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := SafeCreate(dst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, in)
	cerr := out.Close()
	if err != nil {
		return err
	}
	return cerr
}

// SafeCreate creates a file, creating parent directories if needed
func SafeCreate(name ...string) (file *os.File, err error) {
	p, e := ensurePath(path.Join(name...))

	if e != nil {
		return nil, e
	}
	return os.Create(p)
}

func ensurePath(path string) (string, error) {
	base := filepath.Dir(path)
	e, _ := Exists(base)
	if e {
		return path, nil
	}

	// Create missing directory recursively
	err := os.MkdirAll(base, 0777)
	return path, err
}

//Exists - check if the given path exists
func Exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
<|endoftext|>


<commit_before>// +build !windows

package main

import (
	"strconv"
	"strings"

	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/daemon/cluster/executor/container"
	"github.com/docker/docker/integration-cli/checker"
	"github.com/docker/docker/integration-cli/cli"
	"github.com/docker/docker/integration-cli/cli/build"
	"github.com/go-check/check"
	"gotest.tools/assert"
	"gotest.tools/icmd"
)

// start a service, and then make its task unhealthy during running
// finally, unhealthy task should be detected and killed
func (s *DockerSwarmSuite) TestServiceHealthRun(c *check.C) {
	testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows

	d := s.AddDaemon(c, true, true)

	// build image with health-check
	imageName := "testhealth"
	result := cli.BuildCmd(c, imageName, cli.Daemon(d),
		build.WithDockerfile(`FROM busybox
		RUN touch /status
		HEALTHCHECK --interval=1s --timeout=1s --retries=1\
		  CMD cat /status`),
	)
	result.Assert(c, icmd.Success)

	serviceName := "healthServiceRun"
	out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--name", serviceName, imageName, "top")
	assert.NilError(c, err, out)
	id := strings.TrimSpace(out)

	var tasks []swarm.Task
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		tasks = d.GetServiceTasks(c, id)
		return tasks, nil
	}, checker.HasLen, 1)

	task := tasks[0]

	// wait for task to start
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		task = d.GetTask(c, task.ID)
		return task.Status.State, nil
	}, checker.Equals, swarm.TaskStateRunning)
	containerID := task.Status.ContainerStatus.ContainerID

	// wait for container to be healthy
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		out, _ := d.Cmd("inspect", "--format={{.State.Health.Status}}", containerID)
		return strings.TrimSpace(out), nil
	}, checker.Equals, "healthy")

	// make it fail
	d.Cmd("exec", containerID, "rm", "/status")
	// wait for container to be unhealthy
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		out, _ := d.Cmd("inspect", "--format={{.State.Health.Status}}", containerID)
		return strings.TrimSpace(out), nil
	}, checker.Equals, "unhealthy")

	// Task should be terminated
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		task = d.GetTask(c, task.ID)
		return task.Status.State, nil
	}, checker.Equals, swarm.TaskStateFailed)

	if !strings.Contains(task.Status.Err, container.ErrContainerUnhealthy.Error()) {
		c.Fatal("unhealthy task exits because of other error")
	}
}

// start a service whose task is unhealthy at beginning
// its tasks should be blocked in starting stage, until health check is passed
func (s *DockerSwarmSuite) TestServiceHealthStart(c *check.C) {
	testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows

	d := s.AddDaemon(c, true, true)

	// service started from this image won't pass health check
	imageName := "testhealth"
	result := cli.BuildCmd(c, imageName, cli.Daemon(d),
		build.WithDockerfile(`FROM busybox
		HEALTHCHECK --interval=1s --timeout=1s --retries=1024\
		  CMD cat /status`),
	)
	result.Assert(c, icmd.Success)

	serviceName := "healthServiceStart"
	out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--name", serviceName, imageName, "top")
	assert.NilError(c, err, out)
	id := strings.TrimSpace(out)

	var tasks []swarm.Task
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		tasks = d.GetServiceTasks(c, id)
		return tasks, nil
	}, checker.HasLen, 1)

	task := tasks[0]

	// wait for task to start
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		task = d.GetTask(c, task.ID)
		return task.Status.State, nil
	}, checker.Equals, swarm.TaskStateStarting)

	containerID := task.Status.ContainerStatus.ContainerID

	// wait for health check to work
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		out, _ := d.Cmd("inspect", "--format={{.State.Health.FailingStreak}}", containerID)
		failingStreak, _ := strconv.Atoi(strings.TrimSpace(out))
		return failingStreak, nil
	}, checker.GreaterThan, 0)

	// task should be blocked at starting status
	task = d.GetTask(c, task.ID)
	c.Assert(task.Status.State, check.Equals, swarm.TaskStateStarting)

	// make it healthy
	d.Cmd("exec", containerID, "touch", "/status")

	// Task should be at running status
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		task = d.GetTask(c, task.ID)
		return task.Status.State, nil
	}, checker.Equals, swarm.TaskStateRunning)
}
<commit_msg>integration-cli: increase healthcheck timeout<commit_after>// +build !windows

package main

import (
	"strconv"
	"strings"

	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/daemon/cluster/executor/container"
	"github.com/docker/docker/integration-cli/checker"
	"github.com/docker/docker/integration-cli/cli"
	"github.com/docker/docker/integration-cli/cli/build"
	"github.com/go-check/check"
	"gotest.tools/assert"
	"gotest.tools/icmd"
)

// start a service, and then make its task unhealthy during running
// finally, unhealthy task should be detected and killed
func (s *DockerSwarmSuite) TestServiceHealthRun(c *check.C) {
	testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows

	d := s.AddDaemon(c, true, true)

	// build image with health-check
	imageName := "testhealth"
	result := cli.BuildCmd(c, imageName, cli.Daemon(d),
		build.WithDockerfile(`FROM busybox
		RUN touch /status
		HEALTHCHECK --interval=1s --timeout=5s --retries=1\
		  CMD cat /status`),
	)
	result.Assert(c, icmd.Success)

	serviceName := "healthServiceRun"
	out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--name", serviceName, imageName, "top")
	assert.NilError(c, err, out)
	id := strings.TrimSpace(out)

	var tasks []swarm.Task
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		tasks = d.GetServiceTasks(c, id)
		return tasks, nil
	}, checker.HasLen, 1)

	task := tasks[0]

	// wait for task to start
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		task = d.GetTask(c, task.ID)
		return task.Status.State, nil
	}, checker.Equals, swarm.TaskStateRunning)
	containerID := task.Status.ContainerStatus.ContainerID

	// wait for container to be healthy
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		out, _ := d.Cmd("inspect", "--format={{.State.Health.Status}}", containerID)
		return strings.TrimSpace(out), nil
	}, checker.Equals, "healthy")

	// make it fail
	d.Cmd("exec", containerID, "rm", "/status")
	// wait for container to be unhealthy
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		out, _ := d.Cmd("inspect", "--format={{.State.Health.Status}}", containerID)
		return strings.TrimSpace(out), nil
	}, checker.Equals, "unhealthy")

	// Task should be terminated
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		task = d.GetTask(c, task.ID)
		return task.Status.State, nil
	}, checker.Equals, swarm.TaskStateFailed)

	if !strings.Contains(task.Status.Err, container.ErrContainerUnhealthy.Error()) {
		c.Fatal("unhealthy task exits because of other error")
	}
}

// start a service whose task is unhealthy at beginning
// its tasks should be blocked in starting stage, until health check is passed
func (s *DockerSwarmSuite) TestServiceHealthStart(c *check.C) {
	testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows

	d := s.AddDaemon(c, true, true)

	// service started from this image won't pass health check
	imageName := "testhealth"
	result := cli.BuildCmd(c, imageName, cli.Daemon(d),
		build.WithDockerfile(`FROM busybox
		HEALTHCHECK --interval=1s --timeout=1s --retries=1024\
		  CMD cat /status`),
	)
	result.Assert(c, icmd.Success)

	serviceName := "healthServiceStart"
	out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--name", serviceName, imageName, "top")
	assert.NilError(c, err, out)
	id := strings.TrimSpace(out)

	var tasks []swarm.Task
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		tasks = d.GetServiceTasks(c, id)
		return tasks, nil
	}, checker.HasLen, 1)

	task := tasks[0]

	// wait for task to start
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		task = d.GetTask(c, task.ID)
		return task.Status.State, nil
	}, checker.Equals, swarm.TaskStateStarting)

	containerID := task.Status.ContainerStatus.ContainerID

	// wait for health check to work
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		out, _ := d.Cmd("inspect", "--format={{.State.Health.FailingStreak}}", containerID)
		failingStreak, _ := strconv.Atoi(strings.TrimSpace(out))
		return failingStreak, nil
	}, checker.GreaterThan, 0)

	// task should be blocked at starting status
	task = d.GetTask(c, task.ID)
	c.Assert(task.Status.State, check.Equals, swarm.TaskStateStarting)

	// make it healthy
	d.Cmd("exec", containerID, "touch", "/status")

	// Task should be at running status
	waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
		task = d.GetTask(c, task.ID)
		return task.Status.State, nil
	}, checker.Equals, swarm.TaskStateRunning)
}
<|endoftext|>


<commit_before>package imup

import (
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"strconv"
)

// ImageTypes defines the allowed types for an uploaded image.
type ImageTypes map[string]bool

// Image types according to the MIME specification.
var (
	GIF  ImageTypes = ImageTypes{"image/gif": true}
	PNG  ImageTypes = ImageTypes{"image/png": true}
	JPEG ImageTypes = ImageTypes{"image/jpeg": true}
	BMP  ImageTypes = ImageTypes{"image/bmp": true}
	WEBP ImageTypes = ImageTypes{"image/webp": true}
	ICO  ImageTypes = ImageTypes{"image/vnd.microsoft.icon": true}

	// Convenience type for popular web image types.
	PopularTypes ImageTypes = ImageTypes{
		"image/gif":  true,
		"image/png":  true,
		"image/jpeg": true,
	}

	// Convenience type for all image types.
	AllTypes ImageTypes = ImageTypes{
		"image/gif":                true,
		"image/png":                true,
		"image/jpeg":               true,
		"image/bmp":                true,
		"image/webp":               true,
		"image/vnd.microsoft.icon": true,
	}
)

// UploadedImage defines an uploaded image.
type UploadedImage struct {
	Type   string
	file   multipart.File
	header *multipart.FileHeader
}

// Options defines the available options for an image upload.
type Options struct {
	MaxFileSize  int64
	AllowedTypes ImageTypes
}

// New returns a new UploadedImage object if the uploaded file could be parsed
// and validated as an image, otherwise it returns an error.
//
// The key parameter should refer to the name of the file input from the
// multipart form.
func New(key string, r *http.Request, opts *Options) (*UploadedImage, error) {
	var err error
	ui := &UploadedImage{}

	// Handle max file size.
	if opts.MaxFileSize > 0 {
		// Check Content-Length header.
		cl, _ := strconv.ParseInt(r.Header.Get("Content-Length"), 10, 64)
		if cl > opts.MaxFileSize {
			return nil, ErrFileSize
		}

		// Wrap r.Body with limitReader
		r.Body = newLimitReader(r.Body, opts.MaxFileSize)
	}

	// Try to parse the multipart file from the request.
	if ui.file, ui.header, err = r.FormFile(key); err != nil {
		return nil, err
	}

	// Check if type is allowed.
	if len(opts.AllowedTypes) > 0 {
		if err = isTypeAllowed(ui, opts.AllowedTypes); err != nil {
			return nil, err
		}
	}

	return ui, nil
}

// Save saves the uploaded image to the given location and returns the location
// with the correct image extension added on.
//
// The underlying multipart image file is automatically closed.
func (ui *UploadedImage) Save(filename string) (string, error) {
	// Handle the file extension.
	var ext string
	switch ui.Type {
	case "image/gif":
		ext = ".gif"
	case "image/png":
		ext = ".png"
	case "image/jpeg":
		ext = ".jpg"
	case "image/bmp":
		ext = ".bmp"
	case "image/webp":
		ext = ".webp"
	case "image/vnd.microsoft.icon":
		ext = ".ico"
	}
	filename += ext

	// Create output file.
	out, err := os.Create(filename)
	if err != nil {
		return "", err
	}
	defer out.Close()

	// Store the uploaded image to output file.
	_, err = io.Copy(out, ui.file)
	if err != nil {
		return "", err
	}
	ui.Close()

	return filename, nil
}

// Close closes an uploaded image.
func (ui *UploadedImage) Close() {
	ui.file.Close()
}

// isTypeAllowed checks if the given file type is allowed.
func isTypeAllowed(ui *UploadedImage, types ImageTypes) error {
	// Get up to the first 512 bytes of data.
	b := make([]byte, 512)
	_, err := ui.file.Read(b)
	if err != nil {
		return err
	}

	// Reset file pointer.
	if _, err = ui.file.Seek(0, 0); err != nil {
		return err
	}

	// Try to detect the file type.
	ui.Type = http.DetectContentType(b)

	// Validate type.
	if _, ok := types[ui.Type]; !ok {
		return ErrDisallowedType
	}

	return nil
}

// limitReader wraps io.LimitedReader, Read returns ErrFileSize
// when the limit is exceeded rather than io.EOF like io.LimitedReader.
type limitReader struct {
	r *io.LimitedReader
	io.Closer
}

// newLimitReader creates a new limitReader.
func newLimitReader(r io.ReadCloser, maxSize int64) io.ReadCloser {
	return &limitReader{
		r:      io.LimitReader(r, maxSize+1).(*io.LimitedReader),
		Closer: r,
	}
}

// Read satisfies the io.Reader interface.
func (l *limitReader) Read(p []byte) (int, error) {
	n, err := l.r.Read(p)
	if l.r.N < 1 {
		return n, ErrFileSize
	}
	return n, err
}
<commit_msg>- Added error check to UploadedImage Close method<commit_after>package imup

import (
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"strconv"
)

// ImageTypes defines the allowed types for an uploaded image.
type ImageTypes map[string]bool

// Image types according to the MIME specification.
var (
	GIF  ImageTypes = ImageTypes{"image/gif": true}
	PNG  ImageTypes = ImageTypes{"image/png": true}
	JPEG ImageTypes = ImageTypes{"image/jpeg": true}
	BMP  ImageTypes = ImageTypes{"image/bmp": true}
	WEBP ImageTypes = ImageTypes{"image/webp": true}
	ICO  ImageTypes = ImageTypes{"image/vnd.microsoft.icon": true}

	// Convenience type for popular web image types.
	PopularTypes ImageTypes = ImageTypes{
		"image/gif":  true,
		"image/png":  true,
		"image/jpeg": true,
	}

	// Convenience type for all image types.
	AllTypes ImageTypes = ImageTypes{
		"image/gif":                true,
		"image/png":                true,
		"image/jpeg":               true,
		"image/bmp":                true,
		"image/webp":               true,
		"image/vnd.microsoft.icon": true,
	}
)

// UploadedImage defines an uploaded image.
type UploadedImage struct {
	Type   string
	file   multipart.File
	header *multipart.FileHeader
}

// Options defines the available options for an image upload.
type Options struct {
	MaxFileSize  int64
	AllowedTypes ImageTypes
}

// New returns a new UploadedImage object if the uploaded file could be parsed
// and validated as an image, otherwise it returns an error.
//
// The key parameter should refer to the name of the file input from the
// multipart form.
func New(key string, r *http.Request, opts *Options) (*UploadedImage, error) {
	var err error
	ui := &UploadedImage{}

	// Handle max file size.
	if opts.MaxFileSize > 0 {
		// Check Content-Length header.
		cl, _ := strconv.ParseInt(r.Header.Get("Content-Length"), 10, 64)
		if cl > opts.MaxFileSize {
			return nil, ErrFileSize
		}

		// Wrap r.Body with limitReader
		r.Body = newLimitReader(r.Body, opts.MaxFileSize)
	}

	// Try to parse the multipart file from the request.
	if ui.file, ui.header, err = r.FormFile(key); err != nil {
		return nil, err
	}

	// Check if type is allowed.
	if len(opts.AllowedTypes) > 0 {
		if err = isTypeAllowed(ui, opts.AllowedTypes); err != nil {
			return nil, err
		}
	}

	return ui, nil
}

// Save saves the uploaded image to the given location and returns the location
// with the correct image extension added on.
//
// The underlying multipart image file is automatically closed.
func (ui *UploadedImage) Save(filename string) (string, error) {
	// Handle the file extension.
	var ext string
	switch ui.Type {
	case "image/gif":
		ext = ".gif"
	case "image/png":
		ext = ".png"
	case "image/jpeg":
		ext = ".jpg"
	case "image/bmp":
		ext = ".bmp"
	case "image/webp":
		ext = ".webp"
	case "image/vnd.microsoft.icon":
		ext = ".ico"
	}
	filename += ext

	// Create output file.
	out, err := os.Create(filename)
	if err != nil {
		return "", err
	}
	defer out.Close()

	// Store the uploaded image to output file.
	_, err = io.Copy(out, ui.file)
	if err != nil {
		return "", err
	}
	if err = ui.Close(); err != nil {
		return "", err
	}

	return filename, nil
}

// Close closes an uploaded image.
func (ui *UploadedImage) Close() error {
	return ui.file.Close()
}

// isTypeAllowed checks if the given file type is allowed.
func isTypeAllowed(ui *UploadedImage, types ImageTypes) error {
	// Get up to the first 512 bytes of data.
	b := make([]byte, 512)
	_, err := ui.file.Read(b)
	if err != nil {
		return err
	}

	// Reset file pointer.
	if _, err = ui.file.Seek(0, 0); err != nil {
		return err
	}

	// Try to detect the file type.
	ui.Type = http.DetectContentType(b)

	// Validate type.
	if _, ok := types[ui.Type]; !ok {
		return ErrDisallowedType
	}

	return nil
}

// limitReader wraps io.LimitedReader, Read returns ErrFileSize
// when the limit is exceeded rather than io.EOF like io.LimitedReader.
type limitReader struct {
	r *io.LimitedReader
	io.Closer
}

// newLimitReader creates a new limitReader.
func newLimitReader(r io.ReadCloser, maxSize int64) io.ReadCloser {
	return &limitReader{
		r:      io.LimitReader(r, maxSize+1).(*io.LimitedReader),
		Closer: r,
	}
}

// Read satisfies the io.Reader interface.
func (l *limitReader) Read(p []byte) (int, error) {
	n, err := l.r.Read(p)
	if l.r.N < 1 {
		return n, ErrFileSize
	}
	return n, err
}
<|endoftext|>


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

package main

import (
	"net/http"
	"path"
	"regexp"
	"strings"
	"time"

	router "github.com/gorilla/mux"
	"github.com/rs/cors"
)

// HandlerFunc - useful to chain different middleware http.Handler
type HandlerFunc func(http.Handler) http.Handler

func registerHandlers(mux *router.Router, handlerFns ...HandlerFunc) http.Handler {
	var f http.Handler
	f = mux
	for _, hFn := range handlerFns {
		f = hFn(f)
	}
	return f
}

// Adds limiting body size middleware

// Set the body size limit to 6 Gb = Maximum object size + other possible data
// in the same request
const requestMaxBodySize = 1024 * 1024 * 1024 * (5 + 1)

type requestSizeLimitHandler struct {
	handler     http.Handler
	maxBodySize int64
}

func setRequestSizeLimitHandler(h http.Handler) http.Handler {
	return requestSizeLimitHandler{handler: h, maxBodySize: requestMaxBodySize}
}

func (h requestSizeLimitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Restricting read data to a given maximum length
	r.Body = http.MaxBytesReader(w, r.Body, h.maxBodySize)
	h.handler.ServeHTTP(w, r)
}

// Adds redirect rules for incoming requests.
type redirectHandler struct {
	handler        http.Handler
	locationPrefix string
}

// Reserved bucket.
const (
	reservedBucket = "/minio"
)

func setBrowserRedirectHandler(h http.Handler) http.Handler {
	return redirectHandler{handler: h, locationPrefix: reservedBucket}
}

func (h redirectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Re-direction handled specifically for browsers.
	if strings.Contains(r.Header.Get("User-Agent"), "Mozilla") {
		// '/' is redirected to 'locationPrefix/'
		// '/webrpc' is redirected to 'locationPrefix/webrpc'
		// '/login' is redirected to 'locationPrefix/login'
		switch r.URL.Path {
		case "/", "/webrpc", "/login", "/favicon.ico":
			location := h.locationPrefix + r.URL.Path
			// Redirect to new location.
			http.Redirect(w, r, location, http.StatusTemporaryRedirect)
			return
		}
	}
	h.handler.ServeHTTP(w, r)
}

// Adds Cache-Control header
type cacheControlHandler struct {
	handler http.Handler
}

func setBrowserCacheControlHandler(h http.Handler) http.Handler {
	return cacheControlHandler{h}
}

func (h cacheControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" && strings.Contains(r.Header.Get("User-Agent"), "Mozilla") {
		// For all browser requests set appropriate Cache-Control policies
		match, e := regexp.MatchString(reservedBucket+`/([^/]+\.js|favicon.ico)`, r.URL.Path)
		if e != nil {
			writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
			return
		}
		if match {
			// For assets set cache expiry of one year. For each release, the name
			// of the asset name will change and hence it can not be served from cache.
			w.Header().Set("Cache-Control", "max-age=31536000")
		} else if strings.HasPrefix(r.URL.Path, reservedBucket+"/") {
			// For non asset requests we serve index.html which will never be cached.
			w.Header().Set("Cache-Control", "no-store")
		}
	}
	h.handler.ServeHTTP(w, r)
}

// Adds verification for incoming paths.
type minioPrivateBucketHandler struct {
	handler        http.Handler
	reservedBucket string
}

func setPrivateBucketHandler(h http.Handler) http.Handler {
	return minioPrivateBucketHandler{handler: h, reservedBucket: reservedBucket}
}

func (h minioPrivateBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// For all non browser requests, reject access to 'reservedBucket'.
	if !strings.Contains(r.Header.Get("User-Agent"), "Mozilla") && path.Clean(r.URL.Path) == reservedBucket {
		writeErrorResponse(w, r, ErrAllAccessDisabled, r.URL.Path)
		return
	}
	h.handler.ServeHTTP(w, r)
}

// Supported Amz date formats.
var amzDateFormats = []string{
	time.RFC1123,
	time.RFC1123Z,
	iso8601Format,
	// Add new AMZ date formats here.
}

// parseAmzDate - parses date string into supported amz date formats.
func parseAmzDate(amzDateStr string) (amzDate time.Time, apiErr APIErrorCode) {
	for _, dateFormat := range amzDateFormats {
		amzDate, e := time.Parse(dateFormat, amzDateStr)
		if e == nil {
			return amzDate, ErrNone
		}
	}
	return time.Time{}, ErrMalformedDate
}

// Supported Amz date headers.
var amzDateHeaders = []string{
	"x-amz-date",
	"date",
}

// parseAmzDateHeader - parses supported amz date headers, in
// supported amz date formats.
func parseAmzDateHeader(req *http.Request) (time.Time, APIErrorCode) {
	for _, amzDateHeader := range amzDateHeaders {
		amzDateStr := req.Header.Get(http.CanonicalHeaderKey(amzDateHeader))
		if amzDateStr != "" {
			return parseAmzDate(amzDateStr)
		}
	}
	// Date header missing.
	return time.Time{}, ErrMissingDateHeader
}

type timeHandler struct {
	handler http.Handler
}

// setTimeValidityHandler to validate parsable time over http header
func setTimeValidityHandler(h http.Handler) http.Handler {
	return timeHandler{h}
}

func (h timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Verify if date headers are set, if not reject the request
	if _, ok := r.Header["Authorization"]; ok {
		amzDate, apiErr := parseAmzDateHeader(r)
		if apiErr != ErrNone {
			// All our internal APIs are sensitive towards Date
			// header, for all requests where Date header is not
			// present we will reject such clients.
			writeErrorResponse(w, r, apiErr, r.URL.Path)
			return
		}
		// Verify if the request date header is more than 5minutes
		// late, reject such clients.
		if time.Now().UTC().Sub(amzDate)/time.Minute > time.Duration(5)*time.Minute {
			writeErrorResponse(w, r, ErrRequestTimeTooSkewed, r.URL.Path)
			return
		}
	}
	h.handler.ServeHTTP(w, r)
}

type resourceHandler struct {
	handler http.Handler
}

// setCorsHandler handler for CORS (Cross Origin Resource Sharing)
func setCorsHandler(h http.Handler) http.Handler {
	c := cors.New(cors.Options{
		AllowedOrigins: []string{"*"},
		AllowedMethods: []string{"GET", "HEAD", "POST", "PUT"},
		AllowedHeaders: []string{"*"},
		ExposedHeaders: []string{"ETag"},
	})
	return c.Handler(h)
}

// setIgnoreResourcesHandler -
// Ignore resources handler is wrapper handler used for API request resource validation
// Since we do not support all the S3 queries, it is necessary for us to throw back a
// valid error message indicating that requested feature is not implemented.
func setIgnoreResourcesHandler(h http.Handler) http.Handler {
	return resourceHandler{h}
}

// Resource handler ServeHTTP() wrapper
func (h resourceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Skip the first element which is usually '/' and split the rest.
	splits := strings.SplitN(r.URL.Path[1:], "/", 2)

	// Save bucketName and objectName extracted from url Path.
	var bucketName, objectName string
	if len(splits) == 1 {
		bucketName = splits[0]
	}
	if len(splits) == 2 {
		bucketName = splits[0]
		objectName = splits[1]
	}

	// If bucketName is present and not objectName check for bucket level resource queries.
	if bucketName != "" && objectName == "" {
		if ignoreNotImplementedBucketResources(r) {
			writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
			return
		}
	}
	// If bucketName and objectName are present check for its resource queries.
	if bucketName != "" && objectName != "" {
		if ignoreNotImplementedObjectResources(r) {
			writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
			return
		}
	}
	// A put method on path "/" doesn't make sense, ignore it.
	if r.Method == "PUT" && r.URL.Path == "/" {
		writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
		return
	}

	// Serve HTTP.
	h.handler.ServeHTTP(w, r)
}

//// helpers

// Checks requests for not implemented Bucket resources
func ignoreNotImplementedBucketResources(req *http.Request) bool {
	for name := range req.URL.Query() {
		if notimplementedBucketResourceNames[name] {
			return true
		}
	}
	return false
}

// Checks requests for not implemented Object resources
func ignoreNotImplementedObjectResources(req *http.Request) bool {
	for name := range req.URL.Query() {
		if notimplementedObjectResourceNames[name] {
			return true
		}
	}
	return false
}

// List of not implemented bucket queries
var notimplementedBucketResourceNames = map[string]bool{
	"acl":            true,
	"cors":           true,
	"lifecycle":      true,
	"logging":        true,
	"replication":    true,
	"tagging":        true,
	"versions":       true,
	"requestPayment": true,
	"versioning":     true,
	"website":        true,
}

// List of not implemented object queries
var notimplementedObjectResourceNames = map[string]bool{
	"torrent": true,
	"acl":     true,
	"policy":  true,
}
<commit_msg>redirect-middleware: Redirect to /minio only if client is a browser and the request is not V4 signed. (#2469)<commit_after>/*
 * Minio Cloud Storage, (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"net/http"
	"path"
	"regexp"
	"strings"
	"time"

	router "github.com/gorilla/mux"
	"github.com/rs/cors"
)

// HandlerFunc - useful to chain different middleware http.Handler
type HandlerFunc func(http.Handler) http.Handler

func registerHandlers(mux *router.Router, handlerFns ...HandlerFunc) http.Handler {
	var f http.Handler
	f = mux
	for _, hFn := range handlerFns {
		f = hFn(f)
	}
	return f
}

// Adds limiting body size middleware

// Set the body size limit to 6 Gb = Maximum object size + other possible data
// in the same request
const requestMaxBodySize = 1024 * 1024 * 1024 * (5 + 1)

type requestSizeLimitHandler struct {
	handler     http.Handler
	maxBodySize int64
}

func setRequestSizeLimitHandler(h http.Handler) http.Handler {
	return requestSizeLimitHandler{handler: h, maxBodySize: requestMaxBodySize}
}

func (h requestSizeLimitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Restricting read data to a given maximum length
	r.Body = http.MaxBytesReader(w, r.Body, h.maxBodySize)
	h.handler.ServeHTTP(w, r)
}

// Adds redirect rules for incoming requests.
type redirectHandler struct {
	handler        http.Handler
	locationPrefix string
}

// Reserved bucket.
const (
	reservedBucket = "/minio"
)

func setBrowserRedirectHandler(h http.Handler) http.Handler {
	return redirectHandler{handler: h, locationPrefix: reservedBucket}
}

func (h redirectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Re-direction handled specifically for browsers.
	if strings.Contains(r.Header.Get("User-Agent"), "Mozilla") && !isRequestSignatureV4(r) {
		// '/' is redirected to 'locationPrefix/'
		// '/webrpc' is redirected to 'locationPrefix/webrpc'
		// '/login' is redirected to 'locationPrefix/login'
		switch r.URL.Path {
		case "/", "/webrpc", "/login", "/favicon.ico":
			location := h.locationPrefix + r.URL.Path
			// Redirect to new location.
			http.Redirect(w, r, location, http.StatusTemporaryRedirect)
			return
		}
	}
	h.handler.ServeHTTP(w, r)
}

// Adds Cache-Control header
type cacheControlHandler struct {
	handler http.Handler
}

func setBrowserCacheControlHandler(h http.Handler) http.Handler {
	return cacheControlHandler{h}
}

func (h cacheControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" && strings.Contains(r.Header.Get("User-Agent"), "Mozilla") {
		// For all browser requests set appropriate Cache-Control policies
		match, e := regexp.MatchString(reservedBucket+`/([^/]+\.js|favicon.ico)`, r.URL.Path)
		if e != nil {
			writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
			return
		}
		if match {
			// For assets set cache expiry of one year. For each release, the name
			// of the asset name will change and hence it can not be served from cache.
			w.Header().Set("Cache-Control", "max-age=31536000")
		} else if strings.HasPrefix(r.URL.Path, reservedBucket+"/") {
			// For non asset requests we serve index.html which will never be cached.
			w.Header().Set("Cache-Control", "no-store")
		}
	}
	h.handler.ServeHTTP(w, r)
}

// Adds verification for incoming paths.
type minioPrivateBucketHandler struct {
	handler        http.Handler
	reservedBucket string
}

func setPrivateBucketHandler(h http.Handler) http.Handler {
	return minioPrivateBucketHandler{handler: h, reservedBucket: reservedBucket}
}

func (h minioPrivateBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// For all non browser requests, reject access to 'reservedBucket'.
	if !strings.Contains(r.Header.Get("User-Agent"), "Mozilla") && path.Clean(r.URL.Path) == reservedBucket {
		writeErrorResponse(w, r, ErrAllAccessDisabled, r.URL.Path)
		return
	}
	h.handler.ServeHTTP(w, r)
}

// Supported Amz date formats.
var amzDateFormats = []string{
	time.RFC1123,
	time.RFC1123Z,
	iso8601Format,
	// Add new AMZ date formats here.
}

// parseAmzDate - parses date string into supported amz date formats.
func parseAmzDate(amzDateStr string) (amzDate time.Time, apiErr APIErrorCode) {
	for _, dateFormat := range amzDateFormats {
		amzDate, e := time.Parse(dateFormat, amzDateStr)
		if e == nil {
			return amzDate, ErrNone
		}
	}
	return time.Time{}, ErrMalformedDate
}

// Supported Amz date headers.
var amzDateHeaders = []string{
	"x-amz-date",
	"date",
}

// parseAmzDateHeader - parses supported amz date headers, in
// supported amz date formats.
func parseAmzDateHeader(req *http.Request) (time.Time, APIErrorCode) {
	for _, amzDateHeader := range amzDateHeaders {
		amzDateStr := req.Header.Get(http.CanonicalHeaderKey(amzDateHeader))
		if amzDateStr != "" {
			return parseAmzDate(amzDateStr)
		}
	}
	// Date header missing.
	return time.Time{}, ErrMissingDateHeader
}

type timeHandler struct {
	handler http.Handler
}

// setTimeValidityHandler to validate parsable time over http header
func setTimeValidityHandler(h http.Handler) http.Handler {
	return timeHandler{h}
}

func (h timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Verify if date headers are set, if not reject the request
	if _, ok := r.Header["Authorization"]; ok {
		amzDate, apiErr := parseAmzDateHeader(r)
		if apiErr != ErrNone {
			// All our internal APIs are sensitive towards Date
			// header, for all requests where Date header is not
			// present we will reject such clients.
			writeErrorResponse(w, r, apiErr, r.URL.Path)
			return
		}
		// Verify if the request date header is more than 5minutes
		// late, reject such clients.
		if time.Now().UTC().Sub(amzDate)/time.Minute > time.Duration(5)*time.Minute {
			writeErrorResponse(w, r, ErrRequestTimeTooSkewed, r.URL.Path)
			return
		}
	}
	h.handler.ServeHTTP(w, r)
}

type resourceHandler struct {
	handler http.Handler
}

// setCorsHandler handler for CORS (Cross Origin Resource Sharing)
func setCorsHandler(h http.Handler) http.Handler {
	c := cors.New(cors.Options{
		AllowedOrigins: []string{"*"},
		AllowedMethods: []string{"GET", "HEAD", "POST", "PUT"},
		AllowedHeaders: []string{"*"},
		ExposedHeaders: []string{"ETag"},
	})
	return c.Handler(h)
}

// setIgnoreResourcesHandler -
// Ignore resources handler is wrapper handler used for API request resource validation
// Since we do not support all the S3 queries, it is necessary for us to throw back a
// valid error message indicating that requested feature is not implemented.
func setIgnoreResourcesHandler(h http.Handler) http.Handler {
	return resourceHandler{h}
}

// Resource handler ServeHTTP() wrapper
func (h resourceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Skip the first element which is usually '/' and split the rest.
	splits := strings.SplitN(r.URL.Path[1:], "/", 2)

	// Save bucketName and objectName extracted from url Path.
	var bucketName, objectName string
	if len(splits) == 1 {
		bucketName = splits[0]
	}
	if len(splits) == 2 {
		bucketName = splits[0]
		objectName = splits[1]
	}

	// If bucketName is present and not objectName check for bucket level resource queries.
	if bucketName != "" && objectName == "" {
		if ignoreNotImplementedBucketResources(r) {
			writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
			return
		}
	}
	// If bucketName and objectName are present check for its resource queries.
	if bucketName != "" && objectName != "" {
		if ignoreNotImplementedObjectResources(r) {
			writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
			return
		}
	}
	// A put method on path "/" doesn't make sense, ignore it.
	if r.Method == "PUT" && r.URL.Path == "/" {
		writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
		return
	}

	// Serve HTTP.
	h.handler.ServeHTTP(w, r)
}

//// helpers

// Checks requests for not implemented Bucket resources
func ignoreNotImplementedBucketResources(req *http.Request) bool {
	for name := range req.URL.Query() {
		if notimplementedBucketResourceNames[name] {
			return true
		}
	}
	return false
}

// Checks requests for not implemented Object resources
func ignoreNotImplementedObjectResources(req *http.Request) bool {
	for name := range req.URL.Query() {
		if notimplementedObjectResourceNames[name] {
			return true
		}
	}
	return false
}

// List of not implemented bucket queries
var notimplementedBucketResourceNames = map[string]bool{
	"acl":            true,
	"cors":           true,
	"lifecycle":      true,
	"logging":        true,
	"replication":    true,
	"tagging":        true,
	"versions":       true,
	"requestPayment": true,
	"versioning":     true,
	"website":        true,
}

// List of not implemented object queries
var notimplementedObjectResourceNames = map[string]bool{
	"torrent": true,
	"acl":     true,
	"policy":  true,
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	//"gopkg.in/resty.v0"
	//    "github.com/aerth/anaconda"
)

type User struct {
	Name string `json:"name"`
}
type Tweet struct {
	Id                   int64  `json:"id"`
	IdStr                string `json:"id_str"`
	InReplyToScreenName  string `json:"in_reply_to_screen_name"`
	InReplyToStatusID    int64  `json:"in_reply_to_status_id"`
	InReplyToStatusIdStr string `json:"in_reply_to_status_id_str"`
	InReplyToUserID      int64  `json:"in_reply_to_user_id"`
	InReplyToUserIdStr   string `json:"in_reply_to_user_id_str"`
	Lang                 string `json:"lang"`
	Place                string `json:"place"`
	PossiblySensitive    bool   `json:"possibly_sensitive"`
	RetweetCount         int    `json:"retweet_count"`
	Retweeted            bool   `json:"retweeted"`
	RetweetedStatus      *Tweet `json:"retweeted_status"`
	Source               string `json:"source"`

	Text                string   `json:"text"`
	Truncated           bool     `json:"truncated"`
	User                User     `json:"user"`
	WithheldCopyright   bool     `json:"withheld_copyright"`
	WithheldInCountries []string `json:"withheld_in_countries"`
	WithheldScope       string   `json:"withheld_scope"`
}

var fast bool

func init() {
fast = false
}
func main() {
//var tweet Tweet
	log.Println("go-quitter v0.0.1")
	log.Println("Copyright 2016 aerth@sdf.org")

	/* OAuth coming soon.

		if os.Getenv("GNUSOCIALKEY") == "" {
				fmt.Println("Set environmental variable GNUSOCIALKEY before running go-quitter.")
				fmt.Println("GNUSOCIALKEY before running go-quitter.")
				os.Exit(1)
			}
		if os.Getenv("GNUSOCIALSECRET") == "" {
				fmt.Println("Set environmental variable GNUSOCIALSECRET before running go-quitter.")
				os.Exit(1)
		}

		if os.Getenv("GNUSOCIALACCESSTOKEN") == "" {
		 fmt.Println("Set environmental variable GNUSOCIALACCESSTOKEN before running go-quitter.")
		 os.Exit(1)
		}
		if os.Getenv("GNUSOCIALTOKENSECRET") == "" {
		 fmt.Println("Set environmental variable GNUSOCIALTOKENSECRET before running go-quitter.")
		 os.Exit(1)
	 }
	*/

	if len(os.Args) < 2 {
		log.Fatalln("Usage:\n\n\tgo-quitter read\t\t\tReads 20 new posts\n\tgo-quitter read fast\t\tReads 20 new posts (no delay)\n\nYou may set your GNUSOCIALNODE environmental variable to change nodes.\nFor example: `export GNUSOCIALNODE=gs.sdf.org` in your ~/.shrc or ~/.profile\n")
	}

	if os.Args[1] == "read" && len(os.Args) == 2 {
		readNew(false)
		os.Exit(0)
	}
		if os.Args[1] == "read" && os.Args[2] == "fast" {
			readNew(true)
			os.Exit(0)
		}

}
func readNew(fast bool) {

	//var Tweet Tweet
	var gnusocialnode string
	if os.Getenv("GNUSOCIALNODE") == "" {
		gnusocialnode = "gs.sdf.org"
	} else {
		gnusocialnode = os.Getenv("GNUSOCIALNODE")
	}
	log.Println("node: "+gnusocialnode)
	res, err := http.Get("https://" + gnusocialnode + "/api/statuses/public_timeline.json")
	if err != nil {
		log.Fatalln(err)
	}

	body, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()
	var tweets []Tweet
	_ = json.Unmarshal(body, &tweets)

	for i := range tweets {
		fmt.Printf("[" + tweets[i].User.Name + "] " + tweets[i].Text + "\n\n")
		if fast != true { time.Sleep(2000 * time.Millisecond) }
	}

}
<commit_msg>Add example nodes<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	//"gopkg.in/resty.v0"
	//    "github.com/aerth/anaconda"
)

type User struct {
	Name string `json:"name"`
}
type Tweet struct {
	Id                   int64  `json:"id"`
	IdStr                string `json:"id_str"`
	InReplyToScreenName  string `json:"in_reply_to_screen_name"`
	InReplyToStatusID    int64  `json:"in_reply_to_status_id"`
	InReplyToStatusIdStr string `json:"in_reply_to_status_id_str"`
	InReplyToUserID      int64  `json:"in_reply_to_user_id"`
	InReplyToUserIdStr   string `json:"in_reply_to_user_id_str"`
	Lang                 string `json:"lang"`
	Place                string `json:"place"`
	PossiblySensitive    bool   `json:"possibly_sensitive"`
	RetweetCount         int    `json:"retweet_count"`
	Retweeted            bool   `json:"retweeted"`
	RetweetedStatus      *Tweet `json:"retweeted_status"`
	Source               string `json:"source"`

	Text                string   `json:"text"`
	Truncated           bool     `json:"truncated"`
	User                User     `json:"user"`
	WithheldCopyright   bool     `json:"withheld_copyright"`
	WithheldInCountries []string `json:"withheld_in_countries"`
	WithheldScope       string   `json:"withheld_scope"`
}

var fast bool

func init() {
fast = false
}
func main() {
//var tweet Tweet
	log.Println("go-quitter v0.0.1")
	log.Println("Copyright 2016 aerth@sdf.org")

	/* OAuth coming soon.

		if os.Getenv("GNUSOCIALKEY") == "" {
				fmt.Println("Set environmental variable GNUSOCIALKEY before running go-quitter.")
				fmt.Println("GNUSOCIALKEY before running go-quitter.")
				os.Exit(1)
			}
		if os.Getenv("GNUSOCIALSECRET") == "" {
				fmt.Println("Set environmental variable GNUSOCIALSECRET before running go-quitter.")
				os.Exit(1)
		}

		if os.Getenv("GNUSOCIALACCESSTOKEN") == "" {
		 fmt.Println("Set environmental variable GNUSOCIALACCESSTOKEN before running go-quitter.")
		 os.Exit(1)
		}
		if os.Getenv("GNUSOCIALTOKENSECRET") == "" {
		 fmt.Println("Set environmental variable GNUSOCIALTOKENSECRET before running go-quitter.")
		 os.Exit(1)
	 }
	*/

	if len(os.Args) < 2 {
		log.Fatalln("Usage:\n\n\tgo-quitter read\t\t\tReads 20 new posts\n\tgo-quitter read fast\t\tReads 20 new posts (no delay)\n\nYou may set your GNUSOCIALNODE environmental variable to change nodes.\nFor example: `export GNUSOCIALNODE=gs.sdf.org` in your ~/.shrc or ~/.profile\n\nExplore!\n\n\tGNUSOCIALNODE=gnusocial.de ./go-quitter read\n\tGNUSOCIALNODE=quitter.es ./go-quitter read\n\tGNUSOCIALNODE=shitposter.club ./go-quitter read\n\tGNUSOCIALNODE=sealion.club ./go-quitter read\n\t(defaults node is gs.sdf.org)\n")
		}

	if os.Args[1] == "read" && len(os.Args) == 2 {
		readNew(false)
		os.Exit(0)
	}
		if os.Args[1] == "read" && os.Args[2] == "fast" {
			readNew(true)
			os.Exit(0)
		}

}
func readNew(fast bool) {

	//var Tweet Tweet
	var gnusocialnode string
	if os.Getenv("GNUSOCIALNODE") == "" {
		gnusocialnode = "gs.sdf.org"
	} else {
		gnusocialnode = os.Getenv("GNUSOCIALNODE")
	}
	log.Println("node: "+gnusocialnode)
	res, err := http.Get("https://" + gnusocialnode + "/api/statuses/public_timeline.json")
	if err != nil {
		log.Fatalln(err)
	}

	body, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()
	var tweets []Tweet
	_ = json.Unmarshal(body, &tweets)

	for i := range tweets {
		fmt.Printf("[" + tweets[i].User.Name + "] " + tweets[i].Text + "\n\n")
		if fast != true { time.Sleep(2000 * time.Millisecond) }
	}

}
<|endoftext|>