<commit_before>package cmd

import (
	"fmt"

	"github.com/AlecAivazis/survey/v2"
	"github.com/AlecAivazis/survey/v2/terminal"
	"github.com/ory/viper"
	"github.com/spf13/cobra"

	fn "knative.dev/kn-plugin-func"
	"knative.dev/kn-plugin-func/buildpacks"
	"knative.dev/kn-plugin-func/progress"
)

func init() {
	// Add to the root a new "Build" command which obtains an appropriate
	// instance of fn.Client from the given client creator function.
	root.AddCommand(NewBuildCmd(newBuildClient))
}

func newBuildClient(cfg buildConfig) (*fn.Client, error) {
	builder := buildpacks.NewBuilder()
	listener := progress.New()

	builder.Verbose = cfg.Verbose
	listener.Verbose = cfg.Verbose

	return fn.New(
		fn.WithBuilder(builder),
		fn.WithProgressListener(listener),
		fn.WithRegistry(cfg.Registry), // for image name when --image not provided
		fn.WithVerbose(cfg.Verbose)), nil
}

type buildClientFn func(buildConfig) (*fn.Client, error)

func NewBuildCmd(clientFn buildClientFn) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "build",
		Short: "Build a function project as a container image",
		Long: `Build a function project as a container image

This command builds the function project in the current directory or in the directory
specified by --path. The result will be a container image that is pushed to a registry.
The func.yaml file is read to determine the image name and registry.
If the project has not already been built, either --registry or --image must be provided
and the image name is stored in the configuration file.
`,
		Example: `
# Build from the local directory, using the given registry as target.
# The full image name will be determined automatically based on the
# project directory name
kn func build --registry quay.io/myuser

# Build from the local directory, specifying the full image name
kn func build --image quay.io/myuser/myfunc

# Re-build, picking up a previously supplied image name from a local func.yml
kn func build

# Build with a custom buildpack builder
kn func build --builder cnbs/sample-builder:bionic
`,
		SuggestFor: []string{"biuld", "buidl", "built"},
		PreRunE:    bindEnv("image", "path", "builder", "registry", "confirm"),
	}

	cmd.Flags().StringP("builder", "b", "", "Buildpack builder, either an as a an image name or a mapping name.\nSpecified value is stored in func.yaml for subsequent builds.")
	cmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options (Env: $FUNC_CONFIRM)")
	cmd.Flags().StringP("image", "i", "", "Full image name in the orm [registry]/[namespace]/[name]:[tag] (optional). This option takes precedence over --registry (Env: $FUNC_IMAGE")
	cmd.Flags().StringP("path", "p", cwd(), "Path to the project directory (Env: $FUNC_PATH)")
	cmd.Flags().StringP("registry", "r", "", "Registry + namespace part of the image to build, ex 'quay.io/myuser'.  The full image name is automatically determined based on the local directory name. If not provided the registry will be taken from func.yaml (Env: $FUNC_REGISTRY)")

	if err := cmd.RegisterFlagCompletionFunc("builder", CompleteBuilderList); err != nil {
		fmt.Println("internal: error while calling RegisterFlagCompletionFunc: ", err)
	}

	cmd.RunE = func(cmd *cobra.Command, args []string) error {
		return runBuild(cmd, args, clientFn)
	}

	return cmd
}

func runBuild(cmd *cobra.Command, _ []string, clientFn buildClientFn) (err error) {
	config, err := newBuildConfig().Prompt()
	if err != nil {
		if err == terminal.InterruptErr {
			return nil
		}
		return
	}

	function, err := functionWithOverrides(config.Path, functionOverrides{Builder: config.Builder, Image: config.Image})
	if err != nil {
		return
	}

	// Check if the Function has been initialized
	if !function.Initialized() {
		return fmt.Errorf("the given path '%v' does not contain an initialized function. Please create one at this path before deploying", config.Path)
	}

	// If the Function does not yet have an image name and one was not provided on the command line
	if function.Image == "" {
		//  AND a --registry was not provided, then we need to
		// prompt for a registry from which we can derive an image name.
		if config.Registry == "" {
			fmt.Println("A registry for Function images is required. For example, 'docker.io/tigerteam'.")

			err = survey.AskOne(
				&survey.Input{Message: "Registry for Function images:"},
				&config.Registry, survey.WithValidator(survey.Required))
			if err != nil {
				if err == terminal.InterruptErr {
					return nil
				}
				return
			}
		}

		// We have the registry, so let's use it to derive the Function image name
		config.Image = deriveImage(config.Image, config.Registry, config.Path)
		function.Image = config.Image
	}

	// All set, let's write changes in the config to the disk
	err = function.WriteConfig()
	if err != nil {
		return
	}

	client, err := clientFn(config)
	if err != nil {
		return err
	}

	return client.Build(cmd.Context(), config.Path)
}

type buildConfig struct {
	// Image name in full, including registry, repo and tag (overrides
	// image name derivation based on Registry and Function Name)
	Image string

	// Path of the Function implementation on local disk. Defaults to current
	// working directory of the process.
	Path string

	// Push the resulting image to the registry after building.
	Push bool

	// Registry at which interstitial build artifacts should be kept.
	// This setting is ignored if Image is specified, which includes the full
	Registry string

	// Verbose logging.
	Verbose bool

	// Confirm: confirm values arrived upon from environment plus flags plus defaults,
	// with interactive prompting (only applicable when attached to a TTY).
	Confirm bool
	Builder string
}

func newBuildConfig() buildConfig {
	return buildConfig{
		Image:    viper.GetString("image"),
		Path:     viper.GetString("path"),
		Registry: viper.GetString("registry"),
		Verbose:  viper.GetBool("verbose"), // defined on root
		Confirm:  viper.GetBool("confirm"),
		Builder:  viper.GetString("builder"),
	}
}

// Prompt the user with value of config members, allowing for interaractive changes.
// Skipped if not in an interactive terminal (non-TTY), or if --confirm false (agree to
// all prompts) was set (default).
func (c buildConfig) Prompt() (buildConfig, error) {
	imageName := deriveImage(c.Image, c.Registry, c.Path)
	if !interactiveTerminal() || !c.Confirm {
		return c, nil
	}

	bc := buildConfig{Verbose: c.Verbose}

	var qs = []*survey.Question{
		{
			Name: "path",
			Prompt: &survey.Input{
				Message: "Project path:",
				Default: c.Path,
			},
			Validate: survey.Required,
		},
		{
			Name: "image",
			Prompt: &survey.Input{
				Message: "Full image name (e.g. quay.io/boson/node-sample):",
				Default: imageName,
			},
			Validate: survey.Required,
		},
	}
	err := survey.Ask(qs, &bc)

	return bc, err
}
<commit_msg>chore: fix typo in `build` help message (#503)<commit_after>package cmd

import (
	"fmt"

	"github.com/AlecAivazis/survey/v2"
	"github.com/AlecAivazis/survey/v2/terminal"
	"github.com/ory/viper"
	"github.com/spf13/cobra"

	fn "knative.dev/kn-plugin-func"
	"knative.dev/kn-plugin-func/buildpacks"
	"knative.dev/kn-plugin-func/progress"
)

func init() {
	// Add to the root a new "Build" command which obtains an appropriate
	// instance of fn.Client from the given client creator function.
	root.AddCommand(NewBuildCmd(newBuildClient))
}

func newBuildClient(cfg buildConfig) (*fn.Client, error) {
	builder := buildpacks.NewBuilder()
	listener := progress.New()

	builder.Verbose = cfg.Verbose
	listener.Verbose = cfg.Verbose

	return fn.New(
		fn.WithBuilder(builder),
		fn.WithProgressListener(listener),
		fn.WithRegistry(cfg.Registry), // for image name when --image not provided
		fn.WithVerbose(cfg.Verbose)), nil
}

type buildClientFn func(buildConfig) (*fn.Client, error)

func NewBuildCmd(clientFn buildClientFn) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "build",
		Short: "Build a function project as a container image",
		Long: `Build a function project as a container image

This command builds the function project in the current directory or in the directory
specified by --path. The result will be a container image that is pushed to a registry.
The func.yaml file is read to determine the image name and registry.
If the project has not already been built, either --registry or --image must be provided
and the image name is stored in the configuration file.
`,
		Example: `
# Build from the local directory, using the given registry as target.
# The full image name will be determined automatically based on the
# project directory name
kn func build --registry quay.io/myuser

# Build from the local directory, specifying the full image name
kn func build --image quay.io/myuser/myfunc

# Re-build, picking up a previously supplied image name from a local func.yml
kn func build

# Build with a custom buildpack builder
kn func build --builder cnbs/sample-builder:bionic
`,
		SuggestFor: []string{"biuld", "buidl", "built"},
		PreRunE:    bindEnv("image", "path", "builder", "registry", "confirm"),
	}

	cmd.Flags().StringP("builder", "b", "", "Buildpack builder, either an as a an image name or a mapping name.\nSpecified value is stored in func.yaml for subsequent builds.")
	cmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options (Env: $FUNC_CONFIRM)")
	cmd.Flags().StringP("image", "i", "", "Full image name in the form [registry]/[namespace]/[name]:[tag] (optional). This option takes precedence over --registry (Env: $FUNC_IMAGE)")
	cmd.Flags().StringP("path", "p", cwd(), "Path to the project directory (Env: $FUNC_PATH)")
	cmd.Flags().StringP("registry", "r", "", "Registry + namespace part of the image to build, ex 'quay.io/myuser'.  The full image name is automatically determined based on the local directory name. If not provided the registry will be taken from func.yaml (Env: $FUNC_REGISTRY)")

	if err := cmd.RegisterFlagCompletionFunc("builder", CompleteBuilderList); err != nil {
		fmt.Println("internal: error while calling RegisterFlagCompletionFunc: ", err)
	}

	cmd.RunE = func(cmd *cobra.Command, args []string) error {
		return runBuild(cmd, args, clientFn)
	}

	return cmd
}

func runBuild(cmd *cobra.Command, _ []string, clientFn buildClientFn) (err error) {
	config, err := newBuildConfig().Prompt()
	if err != nil {
		if err == terminal.InterruptErr {
			return nil
		}
		return
	}

	function, err := functionWithOverrides(config.Path, functionOverrides{Builder: config.Builder, Image: config.Image})
	if err != nil {
		return
	}

	// Check if the Function has been initialized
	if !function.Initialized() {
		return fmt.Errorf("the given path '%v' does not contain an initialized function. Please create one at this path before deploying", config.Path)
	}

	// If the Function does not yet have an image name and one was not provided on the command line
	if function.Image == "" {
		//  AND a --registry was not provided, then we need to
		// prompt for a registry from which we can derive an image name.
		if config.Registry == "" {
			fmt.Println("A registry for Function images is required. For example, 'docker.io/tigerteam'.")

			err = survey.AskOne(
				&survey.Input{Message: "Registry for Function images:"},
				&config.Registry, survey.WithValidator(survey.Required))
			if err != nil {
				if err == terminal.InterruptErr {
					return nil
				}
				return
			}
		}

		// We have the registry, so let's use it to derive the Function image name
		config.Image = deriveImage(config.Image, config.Registry, config.Path)
		function.Image = config.Image
	}

	// All set, let's write changes in the config to the disk
	err = function.WriteConfig()
	if err != nil {
		return
	}

	client, err := clientFn(config)
	if err != nil {
		return err
	}

	return client.Build(cmd.Context(), config.Path)
}

type buildConfig struct {
	// Image name in full, including registry, repo and tag (overrides
	// image name derivation based on Registry and Function Name)
	Image string

	// Path of the Function implementation on local disk. Defaults to current
	// working directory of the process.
	Path string

	// Push the resulting image to the registry after building.
	Push bool

	// Registry at which interstitial build artifacts should be kept.
	// This setting is ignored if Image is specified, which includes the full
	Registry string

	// Verbose logging.
	Verbose bool

	// Confirm: confirm values arrived upon from environment plus flags plus defaults,
	// with interactive prompting (only applicable when attached to a TTY).
	Confirm bool
	Builder string
}

func newBuildConfig() buildConfig {
	return buildConfig{
		Image:    viper.GetString("image"),
		Path:     viper.GetString("path"),
		Registry: viper.GetString("registry"),
		Verbose:  viper.GetBool("verbose"), // defined on root
		Confirm:  viper.GetBool("confirm"),
		Builder:  viper.GetString("builder"),
	}
}

// Prompt the user with value of config members, allowing for interaractive changes.
// Skipped if not in an interactive terminal (non-TTY), or if --confirm false (agree to
// all prompts) was set (default).
func (c buildConfig) Prompt() (buildConfig, error) {
	imageName := deriveImage(c.Image, c.Registry, c.Path)
	if !interactiveTerminal() || !c.Confirm {
		return c, nil
	}

	bc := buildConfig{Verbose: c.Verbose}

	var qs = []*survey.Question{
		{
			Name: "path",
			Prompt: &survey.Input{
				Message: "Project path:",
				Default: c.Path,
			},
			Validate: survey.Required,
		},
		{
			Name: "image",
			Prompt: &survey.Input{
				Message: "Full image name (e.g. quay.io/boson/node-sample):",
				Default: imageName,
			},
			Validate: survey.Required,
		},
	}
	err := survey.Ask(qs, &bc)

	return bc, err
}
<|endoftext|>


<commit_before>package builder

// nginx
const (
	NginxVersion           = "1.21.6"
	NginxDownloadURLPrefix = "https://nginx.org/download"
)

// pcre
const (
	PcreVersion           = "10.40"
	PcreDownloadURLPrefix = "https://github.com/PhilipHazel/pcre2/releases/download"
)

// openssl
const (
	OpenSSLVersion           = "1.1.1o"
	OpenSSLDownloadURLPrefix = "https://www.openssl.org/source"
)

// libressl
const (
	LibreSSLVersion           = "3.5.2"
	LibreSSLDownloadURLPrefix = "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL"
)

// zlib
const (
	ZlibVersion           = "1.2.12"
	ZlibDownloadURLPrefix = "https://zlib.net"
)

// openResty
const (
	OpenRestyVersion           = "1.19.9.1"
	OpenRestyDownloadURLPrefix = "https://openresty.org/download"
)

// tengine
const (
	TengineVersion           = "2.3.3"
	TengineDownloadURLPrefix = "https://tengine.taobao.org/download"
)

// component enumerations
const (
	ComponentNginx = iota
	ComponentOpenResty
	ComponentTengine
	ComponentPcre
	ComponentOpenSSL
	ComponentLibreSSL
	ComponentZlib
	ComponentMax
)
<commit_msg>bumped default openresty version to 1.21.4.1.<commit_after>package builder

// nginx
const (
	NginxVersion           = "1.21.6"
	NginxDownloadURLPrefix = "https://nginx.org/download"
)

// pcre
const (
	PcreVersion           = "10.40"
	PcreDownloadURLPrefix = "https://github.com/PhilipHazel/pcre2/releases/download"
)

// openssl
const (
	OpenSSLVersion           = "1.1.1o"
	OpenSSLDownloadURLPrefix = "https://www.openssl.org/source"
)

// libressl
const (
	LibreSSLVersion           = "3.5.2"
	LibreSSLDownloadURLPrefix = "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL"
)

// zlib
const (
	ZlibVersion           = "1.2.12"
	ZlibDownloadURLPrefix = "https://zlib.net"
)

// openResty
const (
	OpenRestyVersion           = "1.21.4.1"
	OpenRestyDownloadURLPrefix = "https://openresty.org/download"
)

// tengine
const (
	TengineVersion           = "2.3.3"
	TengineDownloadURLPrefix = "https://tengine.taobao.org/download"
)

// component enumerations
const (
	ComponentNginx = iota
	ComponentOpenResty
	ComponentTengine
	ComponentPcre
	ComponentOpenSSL
	ComponentLibreSSL
	ComponentZlib
	ComponentMax
)
<|endoftext|>


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

package cmd

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

	"github.com/s3git/s3git-go"
	"github.com/cheggaaa/pb"
	"github.com/spf13/cobra"
	"github.com/dustin/go-humanize"
)

// cloneCmd represents the clone command
var cloneCmd = &cobra.Command{
	Use:   "clone [resource]",
	Short: "Clone a repository into a new directory",
	Long: "Clone a repository into a new directory",
	Run: func(cmd *cobra.Command, args []string) {

		if len(args) == 0 {
			er("Missing resource to clone from")
		}

		parts := strings.Split(args[0], "//")
		if len(parts) != 2 {
			er(fmt.Sprintf("Bad resource for cloning (missing '//' separator): %s", args[0]))
		}

		dir, err := filepath.Abs(filepath.Dir("."))
		if err != nil {
			er(err)
		}

		dir += "/" + parts[1]

		// Check whether directory to clone into does not yet exist -- abort otherwise
		if _, err := os.Stat(dir); err == nil {
			er(fmt.Sprintf("Cannot clone into existing directory: %s", dir))
		}

		// Output directory and create it
		fmt.Println("Cloning into", dir)
		err = os.MkdirAll(dir, os.ModePerm)
		if err != nil {
			er(err)
		}

		var barDownloading, barProcessing *pb.ProgressBar

		progressDownload := func(total int64) {
			if barDownloading == nil {
				barDownloading = pb.New64(total).Start()
				barDownloading.Prefix("Downloading ")
			}
			if barDownloading.Increment() == int(total) {
				barDownloading.Finish()
			}
		}

		progressProcessing := func(total int64) {
			if barProcessing == nil {
				barProcessing = pb.New64(total).Start()
				barProcessing.Prefix("Processing  ")
			}
			if barProcessing.Increment() == int(total) {
				barProcessing.Finish()
			}
		}

		options := []s3git.CloneOptions{}
		options = append(options, s3git.CloneOptionSetAccessKey(accessKey))
		options = append(options, s3git.CloneOptionSetSecretKey(secretKey))
		options = append(options, s3git.CloneOptionSetEndpoint(endpoint))

		repo, err := s3git.Clone(args[0], dir, progressDownload, progressProcessing, options...)
		if err != nil {
			er(err)
		}

		outputStats(repo)
	},
}

func outputStats(repo *s3git.Repository) {

	stats, err := repo.Statistics()
	if err == nil {
		fmt.Printf("Done. Totaling %s object%s.\n", humanize.Comma(int64(stats.Objects)), pluralize(stats.Objects))
	}
}

func pluralize(number uint64) string {
	if number != 1 {
		return "s"
	}
	return ""
}

func init() {
	RootCmd.AddCommand(cloneCmd)

	// Add local message flags
	// TODO: 'Duplicate' flags for remote add command -- refactor into single definition
	cloneCmd.Flags().StringVarP(&accessKey, "access", "a", "", "Access key for S3 remote")
	cloneCmd.Flags().StringVarP(&secretKey, "secret", "s", "", "Secret key for S3 remote")
	cloneCmd.Flags().StringVarP(&endpoint, "endpoint", "e", "", "Endpoint for S3 remote")
}<commit_msg>Pass download and processing progress funcs as options parameter to Clone()<commit_after>/*
 * Copyright 2016 Frank Wessels <fwessels@xs4all.nl>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cmd

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

	"github.com/s3git/s3git-go"
	"github.com/cheggaaa/pb"
	"github.com/spf13/cobra"
	"github.com/dustin/go-humanize"
)

// cloneCmd represents the clone command
var cloneCmd = &cobra.Command{
	Use:   "clone [resource]",
	Short: "Clone a repository into a new directory",
	Long: "Clone a repository into a new directory",
	Run: func(cmd *cobra.Command, args []string) {

		if len(args) == 0 {
			er("Missing resource to clone from")
		}

		parts := strings.Split(args[0], "//")
		if len(parts) != 2 {
			er(fmt.Sprintf("Bad resource for cloning (missing '//' separator): %s", args[0]))
		}

		dir, err := filepath.Abs(filepath.Dir("."))
		if err != nil {
			er(err)
		}

		dir += "/" + parts[1]

		// Check whether directory to clone into does not yet exist -- abort otherwise
		if _, err := os.Stat(dir); err == nil {
			er(fmt.Sprintf("Cannot clone into existing directory: %s", dir))
		}

		// Output directory and create it
		fmt.Println("Cloning into", dir)
		err = os.MkdirAll(dir, os.ModePerm)
		if err != nil {
			er(err)
		}

		var barDownloading, barProcessing *pb.ProgressBar

		progressDownload := func(total int64) {
			if barDownloading == nil {
				barDownloading = pb.New64(total).Start()
				barDownloading.Prefix("Downloading ")
			}
			if barDownloading.Increment() == int(total) {
				barDownloading.Finish()
			}
		}

		progressProcessing := func(total int64) {
			if barProcessing == nil {
				barProcessing = pb.New64(total).Start()
				barProcessing.Prefix("Processing  ")
			}
			if barProcessing.Increment() == int(total) {
				barProcessing.Finish()
			}
		}

		options := []s3git.CloneOptions{}
		options = append(options, s3git.CloneOptionSetAccessKey(accessKey))
		options = append(options, s3git.CloneOptionSetSecretKey(secretKey))
		options = append(options, s3git.CloneOptionSetEndpoint(endpoint))
		options = append(options, s3git.CloneOptionSetDownloadProgress(progressDownload))
		options = append(options, s3git.CloneOptionSetProcessingProgress(progressProcessing))

		repo, err := s3git.Clone(args[0], dir, options...)
		if err != nil {
			er(err)
		}

		outputStats(repo)
	},
}

func outputStats(repo *s3git.Repository) {

	stats, err := repo.Statistics()
	if err == nil {
		fmt.Printf("Done. Totaling %s object%s.\n", humanize.Comma(int64(stats.Objects)), pluralize(stats.Objects))
	}
}

func pluralize(number uint64) string {
	if number != 1 {
		return "s"
	}
	return ""
}

func init() {
	RootCmd.AddCommand(cloneCmd)

	// Add local message flags
	// TODO: 'Duplicate' flags for remote add command -- refactor into single definition
	cloneCmd.Flags().StringVarP(&accessKey, "access", "a", "", "Access key for S3 remote")
	cloneCmd.Flags().StringVarP(&secretKey, "secret", "s", "", "Secret key for S3 remote")
	cloneCmd.Flags().StringVarP(&endpoint, "endpoint", "e", "", "Endpoint for S3 remote")
}<|endoftext|>


<commit_before>package builder

// Error is an interface for any error types returned by the builder
// package / during the building process
type Error interface {
	// Error returns the error message to satisfy the error interface
	Error() string

	// ExitCode returns the code that should be used when exiting as a result
	// of this error
	ExitCode() int
}

//... SanitizeError

// SanitizeError is used for errors related to sanitizing a given Bobfile path
type SanitizeError struct {
	message string
}

// Error returns the error message for a SanitizeError.  It is expected to be
// set at the time that the struct instance is created
func (err *SanitizeError) Error() string {
	return err.message
}

// ExitCode returns the exit code for errors related to sanitizing the Bobfile
// path.  It is the same value for all sanitize errors.
func (err *SanitizeError) ExitCode() int {
	return 67
}

//... ParserRelatedError

// ParserRelatedError is used for errors encounted during the building process
// that are related to parsing the Bobfile
type ParserRelatedError struct {
	message  string
	exitCode int
}

// Error returns the error message for a ParserRelatedError.  It is expected to
// be set at the time that the struct instance is created
func (err *ParserRelatedError) Error() string {
	return err.message
}

// ExitCode returns the exit code for errors related to parsing the Bobfile
// path.  It is expected to be set during the time that struct instance is
// created
func (err *ParserRelatedError) ExitCode() int {
	return err.exitCode
}

// BuildRelatedError is used for build-related errors produced by the builder package
// that are encountered during the build process
type BuildRelatedError struct {
	message  string
	exitCode int
}

// Error returns the error message for a build-related error.  It is expected
// to be set at the time that the struct instance is created
func (err *BuildRelatedError) Error() string {
	return err.message
}

// ExitCode returns the exit code for errors related to the build process.  It
// is expected to be set during the time that struct instance is created
func (err *BuildRelatedError) ExitCode() int {
	return err.exitCode
}
<commit_msg>[TRIVIAL] removing some comments<commit_after>package builder

// Error is an interface for any error types returned by the builder
// package / during the building process
type Error interface {
	// Error returns the error message to satisfy the error interface
	Error() string

	// ExitCode returns the code that should be used when exiting as a result
	// of this error
	ExitCode() int
}

// SanitizeError is used for errors related to sanitizing a given Bobfile path
type SanitizeError struct {
	message string
}

// Error returns the error message for a SanitizeError.  It is expected to be
// set at the time that the struct instance is created
func (err *SanitizeError) Error() string {
	return err.message
}

// ExitCode returns the exit code for errors related to sanitizing the Bobfile
// path.  It is the same value for all sanitize errors.
func (err *SanitizeError) ExitCode() int {
	return 67
}

// ParserRelatedError is used for errors encounted during the building process
// that are related to parsing the Bobfile
type ParserRelatedError struct {
	message  string
	exitCode int
}

// Error returns the error message for a ParserRelatedError.  It is expected to
// be set at the time that the struct instance is created
func (err *ParserRelatedError) Error() string {
	return err.message
}

// ExitCode returns the exit code for errors related to parsing the Bobfile
// path.  It is expected to be set during the time that struct instance is
// created
func (err *ParserRelatedError) ExitCode() int {
	return err.exitCode
}

// BuildRelatedError is used for build-related errors produced by the builder package
// that are encountered during the build process
type BuildRelatedError struct {
	message  string
	exitCode int
}

// Error returns the error message for a build-related error.  It is expected
// to be set at the time that the struct instance is created
func (err *BuildRelatedError) Error() string {
	return err.message
}

// ExitCode returns the exit code for errors related to the build process.  It
// is expected to be set during the time that struct instance is created
func (err *BuildRelatedError) ExitCode() int {
	return err.exitCode
}
<|endoftext|>


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

package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// delPrCmd represents the delPr command
var delPrCmd = &cobra.Command{
	Use:   "delPr",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("delPr called")
	},
}

func init() {
	RootCmd.AddCommand(delPrCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// delPrCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// delPrCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
<commit_msg>Update delPr.go<commit_after>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
  "fmt"

  "github.com/spf13/cobra"
)

// delPrCmd represents the delPr command
var delPrCmd = &cobra.Command{
  Use:   "delPr",
  Short: "A brief description of your command",
  Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
  Run: func(cmd *cobra.Command, args []string) {
    title, _ := cmd.Flags().GetString("title")
    prs, _ := cmd.Flags().GetString("pr")
    prs_arr := strings.Split(prs, ",")
    for _, each := range prs_arr {
      meeting.DeleteParticipant(title, each)
    }
  },
}

func init() {
  RootCmd.AddCommand(delPrCmd)

  // Here you will define your flags and configuration settings.

  // Cobra supports Persistent Flags which will work for this command
  // and all subcommands, e.g.:
  // delPrCmd.PersistentFlags().String("foo", "", "A help for foo")

  // Cobra supports local flags which will only run when this command
  // is called directly, e.g.:
  // delPrCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
  delPrCmd.Flags().StringP("title", "t", "", "The title of the meeting the pr wanting to quit.")
  delPrCmd.Flags().StringP("pr", "p", "", "The pr wanting to quit. Please split by ",".")
}
<|endoftext|>


<commit_before>package main

import (
	"html/template"
	"net/http"

	"github.com/gitpods/gitpods/cmd"
	"github.com/gitpods/gitpods/handler"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/gobuffalo/packr"
	"github.com/pressly/chi"
	"github.com/urfave/cli"
)

type uiConf struct {
	Addr     string
	AddrAPI  string
	LogJson  bool
	LogLevel string
}

var (
	uiConfig = uiConf{}

	uiFlags = []cli.Flag{
		cli.StringFlag{
			Name:        cmd.FlagAddr,
			EnvVar:      cmd.EnvAddr,
			Usage:       "The address gitpods UI runs on",
			Value:       ":3010",
			Destination: &uiConfig.Addr,
		},
		cli.StringFlag{
			Name:        cmd.FlagAddrAPI,
			EnvVar:      cmd.EnvAddrAPI,
			Usage:       "The address gitpods API runs on",
			Value:       ":3020",
			Destination: &uiConfig.AddrAPI,
		},
		cli.BoolFlag{
			Name:        cmd.FlagLogJson,
			EnvVar:      cmd.EnvLogJson,
			Usage:       "The logger will log json lines",
			Destination: &uiConfig.LogJson,
		},
		cli.StringFlag{
			Name:        cmd.FlagLogLevel,
			EnvVar:      cmd.EnvLogLevel,
			Usage:       "The log level to filter logs with before printing",
			Value:       "info",
			Destination: &uiConfig.LogLevel,
		},
	}
)

func ActionUI(c *cli.Context) error {
	logger := cmd.NewLogger(uiConfig.LogJson, uiConfig.LogLevel)
	logger = log.WithPrefix(logger, "app", "ui")

	// Create FileServer handler with buffalo's packr to serve file from disk or from within the binary.
	// The path is relative to this file.
	box := packr.NewBox("../../public")

	conf := HTMLConfig{API: uiConfig.AddrAPI}

	r := NewUIRouter(logger, box, conf)

	level.Info(logger).Log("msg", "starting gitpods ui", "addr", uiConfig.Addr)
	return http.ListenAndServe(uiConfig.Addr, r)
}

func NewUIRouter(logger log.Logger, box packr.Box, conf HTMLConfig) *chi.Mux {
	homeHandler := HomeHandler(box, conf)

	r := chi.NewRouter()
	r.Use(handler.LoggerMiddleware(logger))

	r.Get("/", homeHandler)
	r.FileServer("/", box)
	r.NotFound(homeHandler)

	return r
}

type HTMLConfig struct {
	API string `json:"api"`
}

func HomeHandler(box packr.Box, conf HTMLConfig) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		tem, err := template.New("index").Parse(box.String("index.html"))
		if err != nil {
			http.Error(w, "can't open index.html as template", http.StatusInternalServerError)
		}

		tem.Execute(w, conf)
	}
}
<commit_msg>Fix handling the assets in folders not overwriting NotFoundHandler<commit_after>package main

import (
	"html/template"
	"net/http"

	"github.com/gitpods/gitpods/cmd"
	"github.com/gitpods/gitpods/handler"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/gobuffalo/packr"
	"github.com/pressly/chi"
	"github.com/urfave/cli"
)

type uiConf struct {
	Addr     string
	AddrAPI  string
	LogJson  bool
	LogLevel string
}

var (
	uiConfig = uiConf{}

	uiFlags = []cli.Flag{
		cli.StringFlag{
			Name:        cmd.FlagAddr,
			EnvVar:      cmd.EnvAddr,
			Usage:       "The address gitpods UI runs on",
			Value:       ":3010",
			Destination: &uiConfig.Addr,
		},
		cli.StringFlag{
			Name:        cmd.FlagAddrAPI,
			EnvVar:      cmd.EnvAddrAPI,
			Usage:       "The address gitpods API runs on",
			Value:       ":3020",
			Destination: &uiConfig.AddrAPI,
		},
		cli.BoolFlag{
			Name:        cmd.FlagLogJson,
			EnvVar:      cmd.EnvLogJson,
			Usage:       "The logger will log json lines",
			Destination: &uiConfig.LogJson,
		},
		cli.StringFlag{
			Name:        cmd.FlagLogLevel,
			EnvVar:      cmd.EnvLogLevel,
			Usage:       "The log level to filter logs with before printing",
			Value:       "info",
			Destination: &uiConfig.LogLevel,
		},
	}
)

func ActionUI(c *cli.Context) error {
	logger := cmd.NewLogger(uiConfig.LogJson, uiConfig.LogLevel)
	logger = log.WithPrefix(logger, "app", "ui")

	// Create FileServer handler with buffalo's packr to serve file from disk or from within the binary.
	// The path is relative to this file.
	box := packr.NewBox("../../public")

	homeHandler := HomeHandler(box, HTMLConfig{
		API: uiConfig.AddrAPI,
	})

	r := chi.NewRouter()
	r.Use(handler.LoggerMiddleware(logger))

	r.Get("/", homeHandler)
	r.NotFound(homeHandler)

	r.Handle("/favicon.ico", http.FileServer(box))
	r.Handle("/favicon.png", http.FileServer(box))
	r.Handle("/img/*", http.FileServer(box))
	r.Handle("/css/*", http.FileServer(box))
	r.Handle("/js/*", http.FileServer(box))

	level.Info(logger).Log("msg", "starting gitpods ui", "addr", uiConfig.Addr)
	return http.ListenAndServe(uiConfig.Addr, r)
}

type HTMLConfig struct {
	API string `json:"api"`
}

func HomeHandler(box packr.Box, conf HTMLConfig) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		tem, err := template.New("index").Parse(box.String("index.html"))
		if err != nil {
			http.Error(w, "can't open index.html as template", http.StatusInternalServerError)
		}

		tem.Execute(w, conf)
	}
}
<|endoftext|>


<commit_before>package main

import (
	_ "time"
	"crypto/rand"
	"encoding/json"
	"fmt"
	"github.com/gorilla/sessions"
	"io"
	"net/http"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"runtime"
	"errors"
	"html/template"
	"os/exec"
)

var templates = template.Must(template.ParseFiles("index.html"))

const MESSAGE_QUEUE_SIZE = 10

const STATUS_FAILURE = "{\"status\":\"failure\"}"

var authKey = []byte("somesecretauth")
var store sessions.Store

var pool *Pool
var clients map[int64]*Client

var db *sql.DB

type Pool struct {
	in  chan *Client
	out chan *Room
}

type Client struct {
	id      int64
	otherid int64
	in      chan string
	out     chan string
	retChan chan *Room
}

type Room struct {
	id      []byte
	client1 *Client
	client2 *Client
	Question *Question
}

type Question struct {
	Id 	int64			`json:"id"`
	Title string		`json:"title"`
	Body string			`json:"body"`
	Difficulty int 		`json:"diff"`
}

func (p *Pool) Pair() {
	for {
		c1, c2 := <-p.in, <-p.in

		for c1.id == c2.id {
			c2 = <- p.in
		}

		fmt.Println("match found for ", c1.id, " and ", c2.id)

		b := make([]byte, 32)
		n, err := io.ReadFull(rand.Reader, b)
		if err != nil || n != 32 {
			return
		}

		row := db.QueryRow("SELECT * FROM questions ORDER BY RAND()")
		q := new(Question)
		err = row.Scan(&q.Id, &q.Title, &q.Body, &q.Difficulty)
		if err !=  nil {
			fmt.Println(err)
		}

		room := &Room{b, c1, c2, q}

		c1.otherid, c2.otherid = c2.id, c1.id
		c1.in, c2.in = c2.out, c1.out

		c1.retChan <- room
		c2.retChan <- room
	}
}

func newPool() *Pool {
	pool := &Pool{
		in:  make(chan *Client),
		out: make(chan *Room),
	}

	go pool.Pair()

	return pool
}

func UIDFromSession(w http.ResponseWriter, r *http.Request) (int64, error) {
	session, _ := store.Get(r, "session")
	userid := session.Values["userid"]

	if userid == nil {
		return 0, errors.New("no cookie set")
	}
	return userid.(int64), nil
}

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

	db, _ = sql.Open("mysql", "root:pass@/suitup")
	defer db.Close()

	store = sessions.NewCookieStore(authKey)

	pool = newPool()
	clients = make(map[int64]*Client)

	http.HandleFunc("/", mainHandle)

	http.HandleFunc("/login", login)

	http.HandleFunc("/message/check", checkMessage)
	http.HandleFunc("/message/send", sendMessage)

	http.HandleFunc("/question/new", newQuestion)
	http.HandleFunc("/question/submit", testCode)

	http.HandleFunc("/chatroom/join", joinChatRoom)
	http.HandleFunc("/chatroom/leave", leaveChatRoom)

	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("/home/suitup/hackmit/assets/"))))
	http.ListenAndServe(":8080", nil)
}

func mainHandle(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "index.html", nil)
}

func joinChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println("join ", uid)

	retChan := make(chan *Room)
	client := &Client{
		id:      uid,
		in:      nil,
		out:     make(chan string, MESSAGE_QUEUE_SIZE),
		retChan: retChan,
	}

	clients[uid] = client
	pool.in <- client

	chatroom := <- retChan

	fmt.Println("joinChatRoom-chatroom.id: ", chatroom.id)

	qjs, err := json.Marshal(chatroom.Question)

	fmt.Println("qjs: ", string(qjs))

	fmt.Fprint(w, "{\"status\":\"success\",\"crid\":\"", asciify(chatroom.id), "\",\"question\":", string(qjs), "}")
}

func asciify(ba []byte) string {
	ret := make([]byte, len(ba))
	for i, b := range ba {
		ret[i] = (b % 26) + 97
	}
	return string(ret)
}

func testCode(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	code := r.FormValue("submission")
	_ = r.FormValue("cvid")
	qid := "1"
	app := "/home/suitup/hackmit/secure.sh"
	out1, err1 := exec.Command("/usr/bin/secure", qid, code).Output()
	if err1 != nil {
    	fmt.Println(err1)
	}
	fmt.Printf("The date is %s\n", out1)
	out, err := exec.Command(app, qid, code).Output()
    if err != nil {
    	fmt.Println("LOL", err)
    	return
    }
    fmt.Println(string(out))
    fmt.Fprint(w, "{\"status\":\"success\", \"data\": \"", string(out), "\"}" )
    return
}

func leaveChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, _ := UIDFromSession(w, r)
	client := clients[uid]

	if client != nil {
		fmt.Println("leaving")
		delete(clients, client.otherid)
		delete(clients, uid)
	}

	fmt.Println("leave ", uid)

	fmt.Fprint(w, "{\"status\":\"success\"}")
}

func sendMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println("send ", uid)

	r.ParseForm()
	message := r.FormValue("s")

	client := clients[uid]

	if client != nil {
		client.out <- message
		fmt.Fprint(w, "{\"status\":\"success\"}")
	} else {
		fmt.Fprint(w, STATUS_FAILURE)
	}
}

func checkMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println("check ", uid)

	client := clients[uid]

	if client != nil {
		select {
		case message, ok := <- client.in:
			if ok {
				fmt.Fprint(w, "{\"status\":\"success\",\"s\":\"", message, "\"}")
			} else {
				delete(clients, uid)
				fmt.Fprint(w, "{\"status\":\"failure\"}")
			}
		default:
			fmt.Fprint(w, "{\"status\":\"success\",\"s\":\"\"}")
		}

	} else {
		fmt.Fprint(w, "{\"status\":\"failure\",\"s\":\"\"}")
	}
}

type User struct {
    Id            	int64      	`json:"id"`
    FacebookId  	string		`json:fbid"`
    Username 		string		`json:username"`
    Email 			string		`json:email"`
    Level 			int64		`json:lvl"`
    Score 			int64		`json:score"`
}

func newQuestion(w http.ResponseWriter, r *http.Request) {
	row := db.QueryRow("SELECT * FROM questions ORDER BY RAND()")
	q := new(Question)
	err := row.Scan(&q.Id, &q.Title, &q.Body, &q.Difficulty)

	if err != nil {
		fmt.Println(err)
		fmt.Fprint(w, STATUS_FAILURE)
	}

	b, err := json.Marshal(q)
	if err != nil {
		fmt.Println(err)
		fmt.Fprint(w, STATUS_FAILURE)
	}

	fmt.Fprint(w, string(b))
}

func login(w http.ResponseWriter, r *http.Request) {
	inputToken := r.FormValue("access_token")
	if len(inputToken) != 0 {
		uid := GetMe(inputToken)

		// row := db.QueryRow("SELECT id FROM users")
		row := db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
		user := new(User)
		err := row.Scan(&user.Id)

		if err != nil {
			_, err = db.Exec("INSERT INTO users (facebook_id, username, email, level, points) VALUES (?, ?, ?, 0, 0)", uid, "", "")
			if err != nil {
				fmt.Fprint(w, STATUS_FAILURE)
				return
			} else {
				row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
				err = row.Scan(&user.Id)
				if err != nil {
					fmt.Fprint(w, STATUS_FAILURE)
					return
				}
			}

		}

		session, _ := store.Get(r, "session")
		session.Values["userid"] = user.Id
		session.Save(r, w)

		fmt.Fprint(w, "{\"status\":\"success\"}")
	}
}

func readHttpBody(response *http.Response) string {
	bodyBuffer := make([]byte, 1000)
	var str string

	count, err := response.Body.Read(bodyBuffer)

	for ; count > 0; count, err = response.Body.Read(bodyBuffer) {

		if err != nil {

		}

		str += string(bodyBuffer[:count])
	}

	return str

}

func getUncachedResponse(uri string) (*http.Response, error) {
	request, err := http.NewRequest("GET", uri, nil)

	if err == nil {
		request.Header.Add("Cache-Control", "no-cache")

		client := new(http.Client)

		return client.Do(request)
	}

	if (err != nil) {
	}
	return nil, err

}

func GetMe(token string) string {
	response, err := getUncachedResponse("https://graph.facebook.com/me?access_token="+token)

	if err == nil {

		var jsonBlob interface{}

		responseBody := readHttpBody(response)

		if responseBody != "" {
			err = json.Unmarshal([]byte(responseBody), &jsonBlob)

			if err == nil {
				jsonObj := jsonBlob.(map[string]interface{})
				return jsonObj["id"].(string)
			}
		}
		return err.Error()
	}

	return err.Error()
}

func handleError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>adding changes to bash call<commit_after>package main

import (
	_ "time"
	"crypto/rand"
	"encoding/json"
	"fmt"
	"github.com/gorilla/sessions"
	"io"
	"net/http"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"runtime"
	"errors"
	"html/template"
	"os/exec"
)

var templates = template.Must(template.ParseFiles("index.html"))

const MESSAGE_QUEUE_SIZE = 10

const STATUS_FAILURE = "{\"status\":\"failure\"}"

var authKey = []byte("somesecretauth")
var store sessions.Store

var pool *Pool
var clients map[int64]*Client

var db *sql.DB

type Pool struct {
	in  chan *Client
	out chan *Room
}

type Client struct {
	id      int64
	otherid int64
	in      chan string
	out     chan string
	retChan chan *Room
}

type Room struct {
	id      []byte
	client1 *Client
	client2 *Client
	Question *Question
}

type Question struct {
	Id 	int64			`json:"id"`
	Title string		`json:"title"`
	Body string			`json:"body"`
	Difficulty int 		`json:"diff"`
}

func (p *Pool) Pair() {
	for {
		c1, c2 := <-p.in, <-p.in

		for c1.id == c2.id {
			c2 = <- p.in
		}

		fmt.Println("match found for ", c1.id, " and ", c2.id)

		b := make([]byte, 32)
		n, err := io.ReadFull(rand.Reader, b)
		if err != nil || n != 32 {
			return
		}

		row := db.QueryRow("SELECT * FROM questions ORDER BY RAND()")
		q := new(Question)
		err = row.Scan(&q.Id, &q.Title, &q.Body, &q.Difficulty)
		if err !=  nil {
			fmt.Println(err)
		}

		room := &Room{b, c1, c2, q}

		c1.otherid, c2.otherid = c2.id, c1.id
		c1.in, c2.in = c2.out, c1.out

		c1.retChan <- room
		c2.retChan <- room
	}
}

func newPool() *Pool {
	pool := &Pool{
		in:  make(chan *Client),
		out: make(chan *Room),
	}

	go pool.Pair()

	return pool
}

func UIDFromSession(w http.ResponseWriter, r *http.Request) (int64, error) {
	session, _ := store.Get(r, "session")
	userid := session.Values["userid"]

	if userid == nil {
		return 0, errors.New("no cookie set")
	}
	return userid.(int64), nil
}

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

	db, _ = sql.Open("mysql", "root:pass@/suitup")
	defer db.Close()

	store = sessions.NewCookieStore(authKey)

	pool = newPool()
	clients = make(map[int64]*Client)

	http.HandleFunc("/", mainHandle)

	http.HandleFunc("/login", login)

	http.HandleFunc("/message/check", checkMessage)
	http.HandleFunc("/message/send", sendMessage)

	http.HandleFunc("/question/new", newQuestion)
	http.HandleFunc("/question/submit", testCode)

	http.HandleFunc("/chatroom/join", joinChatRoom)
	http.HandleFunc("/chatroom/leave", leaveChatRoom)

	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("/home/suitup/hackmit/assets/"))))
	http.ListenAndServe(":8080", nil)
}

func mainHandle(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "index.html", nil)
}

func joinChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println("join ", uid)

	retChan := make(chan *Room)
	client := &Client{
		id:      uid,
		in:      nil,
		out:     make(chan string, MESSAGE_QUEUE_SIZE),
		retChan: retChan,
	}

	clients[uid] = client
	pool.in <- client

	chatroom := <- retChan

	fmt.Println("joinChatRoom-chatroom.id: ", chatroom.id)

	qjs, err := json.Marshal(chatroom.Question)

	fmt.Println("qjs: ", string(qjs))

	fmt.Fprint(w, "{\"status\":\"success\",\"crid\":\"", asciify(chatroom.id), "\",\"question\":", string(qjs), "}")
}

func asciify(ba []byte) string {
	ret := make([]byte, len(ba))
	for i, b := range ba {
		ret[i] = (b % 26) + 97
	}
	return string(ret)
}

func testCode(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	code := r.FormValue("submission")
	_ = r.FormValue("cvid")
	qid := "1"
	app := "/usr/bin/secure"
	out1, err1 := exec.Command("/usr/bin/secure", qid, code).Output()
	if err1 != nil {
    	fmt.Println(err1)
	}
	fmt.Printf("The date is %s\n", out1)
	out, err := exec.Command(app, qid, code).Output()
    if err != nil {
    	fmt.Println("LOL", err)
    	return
    }
    fmt.Println(string(out))
    fmt.Fprint(w, "{\"status\":\"success\", \"data\": \"", string(out), "\"}" )
    return
}

func leaveChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, _ := UIDFromSession(w, r)
	client := clients[uid]

	if client != nil {
		fmt.Println("leaving")
		delete(clients, client.otherid)
		delete(clients, uid)
	}

	fmt.Println("leave ", uid)

	fmt.Fprint(w, "{\"status\":\"success\"}")
}

func sendMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println("send ", uid)

	r.ParseForm()
	message := r.FormValue("s")

	client := clients[uid]

	if client != nil {
		client.out <- message
		fmt.Fprint(w, "{\"status\":\"success\"}")
	} else {
		fmt.Fprint(w, STATUS_FAILURE)
	}
}

func checkMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println("check ", uid)

	client := clients[uid]

	if client != nil {
		select {
		case message, ok := <- client.in:
			if ok {
				fmt.Fprint(w, "{\"status\":\"success\",\"s\":\"", message, "\"}")
			} else {
				delete(clients, uid)
				fmt.Fprint(w, "{\"status\":\"failure\"}")
			}
		default:
			fmt.Fprint(w, "{\"status\":\"success\",\"s\":\"\"}")
		}

	} else {
		fmt.Fprint(w, "{\"status\":\"failure\",\"s\":\"\"}")
	}
}

type User struct {
    Id            	int64      	`json:"id"`
    FacebookId  	string		`json:fbid"`
    Username 		string		`json:username"`
    Email 			string		`json:email"`
    Level 			int64		`json:lvl"`
    Score 			int64		`json:score"`
}

func newQuestion(w http.ResponseWriter, r *http.Request) {
	row := db.QueryRow("SELECT * FROM questions ORDER BY RAND()")
	q := new(Question)
	err := row.Scan(&q.Id, &q.Title, &q.Body, &q.Difficulty)

	if err != nil {
		fmt.Println(err)
		fmt.Fprint(w, STATUS_FAILURE)
	}

	b, err := json.Marshal(q)
	if err != nil {
		fmt.Println(err)
		fmt.Fprint(w, STATUS_FAILURE)
	}

	fmt.Fprint(w, string(b))
}

func login(w http.ResponseWriter, r *http.Request) {
	inputToken := r.FormValue("access_token")
	if len(inputToken) != 0 {
		uid := GetMe(inputToken)

		// row := db.QueryRow("SELECT id FROM users")
		row := db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
		user := new(User)
		err := row.Scan(&user.Id)

		if err != nil {
			_, err = db.Exec("INSERT INTO users (facebook_id, username, email, level, points) VALUES (?, ?, ?, 0, 0)", uid, "", "")
			if err != nil {
				fmt.Fprint(w, STATUS_FAILURE)
				return
			} else {
				row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
				err = row.Scan(&user.Id)
				if err != nil {
					fmt.Fprint(w, STATUS_FAILURE)
					return
				}
			}

		}

		session, _ := store.Get(r, "session")
		session.Values["userid"] = user.Id
		session.Save(r, w)

		fmt.Fprint(w, "{\"status\":\"success\"}")
	}
}

func readHttpBody(response *http.Response) string {
	bodyBuffer := make([]byte, 1000)
	var str string

	count, err := response.Body.Read(bodyBuffer)

	for ; count > 0; count, err = response.Body.Read(bodyBuffer) {

		if err != nil {

		}

		str += string(bodyBuffer[:count])
	}

	return str

}

func getUncachedResponse(uri string) (*http.Response, error) {
	request, err := http.NewRequest("GET", uri, nil)

	if err == nil {
		request.Header.Add("Cache-Control", "no-cache")

		client := new(http.Client)

		return client.Do(request)
	}

	if (err != nil) {
	}
	return nil, err

}

func GetMe(token string) string {
	response, err := getUncachedResponse("https://graph.facebook.com/me?access_token="+token)

	if err == nil {

		var jsonBlob interface{}

		responseBody := readHttpBody(response)

		if responseBody != "" {
			err = json.Unmarshal([]byte(responseBody), &jsonBlob)

			if err == nil {
				jsonObj := jsonBlob.(map[string]interface{})
				return jsonObj["id"].(string)
			}
		}
		return err.Error()
	}

	return err.Error()
}

func handleError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


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

package client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"reflect"
	"testing"

	"github.com/romana/core/common/api"
)

/*
var (
	client *Client
	// Keep track of state of some tests
	state int
)

func init() {
	rand.Seed(time.Now().UnixNano())
	testSaver = &TestSaver{}
}

func tearDown(t *testing.T) {
	var err error
	err = client.Store.DeleteTree(client.config.EtcdPrefix)
	if err != nil {
		t.Errorf("Error tearing down: %s", err)
	}
	t.Logf("Tore down %s", client.config.EtcdPrefix)
}

func initClient(t *testing.T, topoConf string) *Client {
	var err error
	cfg := &common.Config{EtcdEndpoints: []string{"localhost:2379"},
		EtcdPrefix: fmt.Sprintf("/romanaTest%d", rand.Int63n(100000)),
	}
	client, err := NewClient(cfg)
	if err != nil {
		t.Fatal(err)
	}
	if topoConf != "" {
		topoReq := api.TopologyUpdateRequest{}
		err = json.Unmarshal([]byte(topoConf), &topoReq)
		if err != nil {
			t.Fatalf("Cannot parse %s: %v", topoConf, err)
		}
		err = client.IPAM.UpdateTopology(topoReq, false)
		if err != nil {
			t.Fatal(err)
		}
	}
	return client
}
*/

// TestWatchHostsWithCallback tests WatchHostsWithCallback -- and since it
// uses WatchHosts internally, implicitly also WatchHosts
/*
func TestWatchHostsWithCallback(t *testing.T) {
	client := initClient(t, "")
	defer tearDown(t)
	errCh := make(chan string)
	okCh := make(chan string)
	err := client.WatchHostsWithCallback(func(hl api.HostList) {
		state++

		var msg string
		fmt.Printf("HostListCallback: Got host list of length %d and revision %d in state %d\n", len(hl.Hosts), hl.Revision, state)
		if state == 1 {
			if len(hl.Hosts) != 0 {
				msg = fmt.Sprintf("HostListCallback: Expected host length at this point to be 0, got %d", len(hl.Hosts))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != 0 {
				msg = fmt.Sprintf("HostListCallback: Expected host list revision at this point to be 0, got %d", hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}
		} else if state == 2 {
			if len(hl.Hosts) != 2 {
				msg = fmt.Sprintf("HostListCallback: Expected host length at this point to be 2, got %d", len(hl.Hosts))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != 1 {
				msg = fmt.Sprintf("HostListCallback: Expected host list revision at this point to be 1, got %d", hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}
			// Here everything is ok!
			okCh <- "OK"
		} else {
			msg = fmt.Sprintf("HostListCallback: Did not expect HostListCallback to be called in state %d", state)
			fmt.Println(state)
			errCh <- msg

		}

	})
	if err != nil {
		t.Fatal(err)
	}

	topoConf := `{
	"networks": [{
		"name": "net1",
		"cidr": "10.0.0.0/8",
		"block_mask": 30
	}],

	"topologies": [{
		"networks": ["net1"],
		"map": [{
			"routing": "bla",
			"groups": [{
					"name": "host1",
					"ip": "192.168.99.10"
				},
				{
					"name": "host2",
					"ip": "192.168.99.11"
				}
			]
		}]
	}]
}`
	topoReq := api.TopologyUpdateRequest{}
	err = json.Unmarshal([]byte(topoConf), &topoReq)
	if err != nil {
		t.Fatalf("Cannot parse %s: %v", topoConf, err)
	}
	err = client.IPAM.UpdateTopology(topoReq)
	if err != nil {
		t.Fatal(err)
	}
	for {
		select {
		case msg := <-errCh:
			t.Fatal(msg)
			break
		case <-okCh:
			return
		}
	}

}
*/

// TestWatchBlocksWithCallback tests WatchBlocksWithCallback -- and since it
// uses WatchBlocks internally, implicitly also WatchBlocks
/*
func TestWatchBlocksWithCallback(t *testing.T) {
	defer tearDown(t)
	errCh := make(chan string)
	okCh := make(chan string)
	topoConf := `{
	"networks": [{
		"name": "net1",
		"cidr": "10.0.0.0/8",
		"block_mask": 31
	}],

	"topologies": [{
		"networks": ["net1"],
		"map": [{
			"routing": "bla",
			"groups": [{
					"name": "host1",
					"ip": "192.168.99.10"
				},
				{
					"name": "host2",
					"ip": "192.168.99.11"
				}
			]
		}]
	}]
}`
	client = initClient(t, topoConf)
	err := client.WatchBlocksWithCallback(func(hl api.IPAMBlocksResponse) {
		state++

		var msg string
		fmt.Printf("BlocksListCallback: Got block list of length %d and revision %d in state %d\n", len(hl.Blocks), hl.Revision, state)
		switch state {
		case 1:
			if len(hl.Blocks) != 0 {
				msg = fmt.Sprintf("BlocksListCallback: Expected block length at this point to be 0, got %d", len(hl.Blocks))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != 0 {
				msg = fmt.Sprintf("BlocksListCallback: Expected block list revision at this point to be 0, got %d", hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}
		case 2, 3:
			if len(hl.Blocks) != 1 {
				msg = fmt.Sprintf("BlocksListCallback: Expected block length at this point to be 1, got %d", len(hl.Blocks))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != state-1 {
				msg = fmt.Sprintf("HostListCallback: Expected block list revision at this point to be %d, got %d", state-1, hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}

		case 4, 5:
			if len(hl.Blocks) != 2 {
				msg = fmt.Sprintf("BlocksListCallback: Expected block length at this point to be 2, got %d", len(hl.Blocks))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != state-1 {
				msg = fmt.Sprintf("HostListCallback: Expected block list revision at this point to be %d, got %d", state-1, hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if state == 5 {
				// Here everything is ok!
				okCh <- "OK"
			}
		default:
			msg = fmt.Sprintf("HostListCallback: Did not expect HostListCallback to be called in state %d", state)
			errCh <- msg

		}

	})
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.IPAM.AllocateIP("addr1", "host1", "t1", "s1")
	if err != nil {
		t.Fatal(err)
	}
	_, err = client.IPAM.AllocateIP("addr2", "host1", "t1", "s1")
	if err != nil {
		t.Fatal(err)
	}
	_, err = client.IPAM.AllocateIP("addr3", "host1", "t1", "s1")
	if err != nil {
		t.Fatal(err)
	}
	_, err = client.IPAM.AllocateIP("addr4", "host1", "t1", "s1")
	if err != nil {
		t.Fatal(err)
	}
	for {
		select {
		case msg := <-errCh:
			t.Fatal(msg)
			break
		case <-okCh:
			return
		}
	}
}
*/

/*
func TestConcurrency(t *testing.T) {
	//	defer tearDown(t)
	client = initClient(t, "")

	barrier := make(chan int)
	cnt := 8
	locker, err := client.Store.NewLocker("/lock")
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < cnt; i++ {
		go func(i int) {
			fmt.Printf("%d %d Entered\n", i, getGID())
			defer func(i int) {
				fmt.Printf("%d %d Unlocking\n", i, getGID())
				locker.Unlock()
				fmt.Printf("%d %d Unlocked\n", i, getGID())
			}(i)
			fmt.Printf("%d %d Waiting for lock\n", i, getGID())
			locker.Lock()
			fmt.Printf("%d %d Got lock\n", i, getGID())
			val := fmt.Sprintf("Hello from %d %d", i, getGID())
			err := client.Store.Put(fmt.Sprintf("/test%d", i), []byte(val), nil)
			if err != nil {
				fmt.Println(err)
			}
			barrier <- 1
		}(i)
	}
	finishedCnt := 0

WAIT_FOR_FINISH:
	for {
		select {
		case <-barrier:
			finishedCnt++
			fmt.Printf("%d routines finished\n", finishedCnt)
			if finishedCnt == cnt {
				break WAIT_FOR_FINISH
			}
		}
	}
}
*/

type testcase struct {
	name string
	ipam *IPAM
	want interface{}
}

func loadTestFiles(name string, inFile string, outFile string) (testcase, error) {
	input, err := ioutil.ReadFile(inFile)
	if err != nil {
		return testcase{}, fmt.Errorf("error reading test input file: %s", err)
	}
	output, err := ioutil.ReadFile(outFile)
	if err != nil {
		return testcase{}, fmt.Errorf("error reading test output file: %s", err)
	}

	ipamState := &IPAM{}
	err = json.Unmarshal(input, ipamState)
	if err != nil {
		return testcase{}, fmt.Errorf("failed to unmarshal ipam information: %s", err)
	}
	topologyState := &api.TopologyUpdateRequest{}
	err = json.Unmarshal(output, topologyState)
	if err != nil {
		return testcase{}, fmt.Errorf("failed to unmarshal topology information: %s", err)
	}

	return testcase{name, ipamState, topologyState}, nil
}

func Test_getTopologyFromIPAMState(t *testing.T) {
	var testcases []testcase

	testfiles := map[string][]string{
		"multinetwork": {
			"testdata/TestTopologyGetInputMultiNetworks.json",
			"testdata/TestTopologyGetOutputMultiNetworks.json",
		},
		"kubeadm": {
			"testdata/TestTopologyGetInputKubeadm.json",
			"testdata/TestTopologyGetOutputKubeadm.json",
		},
	}

	for name, file := range testfiles {
		tc, err := loadTestFiles(name, file[0], file[1])
		if err != nil {
			t.Errorf("error loading test files: %s", err)
			continue
		}
		testcases = append(testcases, tc)
	}

	for _, tt := range testcases {
		t.Run(tt.name, func(t *testing.T) {
			// TODO: got and tt.want below are not sorted, so there is a fair chance the
			// testcases here may fail, in which case this needs to be fixed by sorting
			// it first.
			if got := getTopologyFromIPAMState(tt.ipam); !reflect.DeepEqual(got, tt.want) {
				bodyGot, errGot := json.MarshalIndent(got, "", "\t")
				bodyWant, errWant := json.MarshalIndent(tt.want, "", "\t")
				if errGot == nil && errWant == nil {
					t.Errorf("getTopology() = \ngot(%s)\nwant(%s)",
						string(bodyGot), string(bodyWant))
				} else {
					t.Errorf("getTopology() = \ngot(%#v)\nwant(%#v)", got, tt.want)
				}
			}
		})
	}
}
<commit_msg>ipam-client: fix test case to sort results.<commit_after>// Copyright (c) 2017 Pani Networks
// All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

package client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"reflect"
	"sort"
	"testing"

	"github.com/romana/core/common/api"
)

/*
var (
	client *Client
	// Keep track of state of some tests
	state int
)

func init() {
	rand.Seed(time.Now().UnixNano())
	testSaver = &TestSaver{}
}

func tearDown(t *testing.T) {
	var err error
	err = client.Store.DeleteTree(client.config.EtcdPrefix)
	if err != nil {
		t.Errorf("Error tearing down: %s", err)
	}
	t.Logf("Tore down %s", client.config.EtcdPrefix)
}

func initClient(t *testing.T, topoConf string) *Client {
	var err error
	cfg := &common.Config{EtcdEndpoints: []string{"localhost:2379"},
		EtcdPrefix: fmt.Sprintf("/romanaTest%d", rand.Int63n(100000)),
	}
	client, err := NewClient(cfg)
	if err != nil {
		t.Fatal(err)
	}
	if topoConf != "" {
		topoReq := api.TopologyUpdateRequest{}
		err = json.Unmarshal([]byte(topoConf), &topoReq)
		if err != nil {
			t.Fatalf("Cannot parse %s: %v", topoConf, err)
		}
		err = client.IPAM.UpdateTopology(topoReq, false)
		if err != nil {
			t.Fatal(err)
		}
	}
	return client
}
*/

// TestWatchHostsWithCallback tests WatchHostsWithCallback -- and since it
// uses WatchHosts internally, implicitly also WatchHosts
/*
func TestWatchHostsWithCallback(t *testing.T) {
	client := initClient(t, "")
	defer tearDown(t)
	errCh := make(chan string)
	okCh := make(chan string)
	err := client.WatchHostsWithCallback(func(hl api.HostList) {
		state++

		var msg string
		fmt.Printf("HostListCallback: Got host list of length %d and revision %d in state %d\n", len(hl.Hosts), hl.Revision, state)
		if state == 1 {
			if len(hl.Hosts) != 0 {
				msg = fmt.Sprintf("HostListCallback: Expected host length at this point to be 0, got %d", len(hl.Hosts))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != 0 {
				msg = fmt.Sprintf("HostListCallback: Expected host list revision at this point to be 0, got %d", hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}
		} else if state == 2 {
			if len(hl.Hosts) != 2 {
				msg = fmt.Sprintf("HostListCallback: Expected host length at this point to be 2, got %d", len(hl.Hosts))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != 1 {
				msg = fmt.Sprintf("HostListCallback: Expected host list revision at this point to be 1, got %d", hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}
			// Here everything is ok!
			okCh <- "OK"
		} else {
			msg = fmt.Sprintf("HostListCallback: Did not expect HostListCallback to be called in state %d", state)
			fmt.Println(state)
			errCh <- msg

		}

	})
	if err != nil {
		t.Fatal(err)
	}

	topoConf := `{
	"networks": [{
		"name": "net1",
		"cidr": "10.0.0.0/8",
		"block_mask": 30
	}],

	"topologies": [{
		"networks": ["net1"],
		"map": [{
			"routing": "bla",
			"groups": [{
					"name": "host1",
					"ip": "192.168.99.10"
				},
				{
					"name": "host2",
					"ip": "192.168.99.11"
				}
			]
		}]
	}]
}`
	topoReq := api.TopologyUpdateRequest{}
	err = json.Unmarshal([]byte(topoConf), &topoReq)
	if err != nil {
		t.Fatalf("Cannot parse %s: %v", topoConf, err)
	}
	err = client.IPAM.UpdateTopology(topoReq)
	if err != nil {
		t.Fatal(err)
	}
	for {
		select {
		case msg := <-errCh:
			t.Fatal(msg)
			break
		case <-okCh:
			return
		}
	}

}
*/

// TestWatchBlocksWithCallback tests WatchBlocksWithCallback -- and since it
// uses WatchBlocks internally, implicitly also WatchBlocks
/*
func TestWatchBlocksWithCallback(t *testing.T) {
	defer tearDown(t)
	errCh := make(chan string)
	okCh := make(chan string)
	topoConf := `{
	"networks": [{
		"name": "net1",
		"cidr": "10.0.0.0/8",
		"block_mask": 31
	}],

	"topologies": [{
		"networks": ["net1"],
		"map": [{
			"routing": "bla",
			"groups": [{
					"name": "host1",
					"ip": "192.168.99.10"
				},
				{
					"name": "host2",
					"ip": "192.168.99.11"
				}
			]
		}]
	}]
}`
	client = initClient(t, topoConf)
	err := client.WatchBlocksWithCallback(func(hl api.IPAMBlocksResponse) {
		state++

		var msg string
		fmt.Printf("BlocksListCallback: Got block list of length %d and revision %d in state %d\n", len(hl.Blocks), hl.Revision, state)
		switch state {
		case 1:
			if len(hl.Blocks) != 0 {
				msg = fmt.Sprintf("BlocksListCallback: Expected block length at this point to be 0, got %d", len(hl.Blocks))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != 0 {
				msg = fmt.Sprintf("BlocksListCallback: Expected block list revision at this point to be 0, got %d", hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}
		case 2, 3:
			if len(hl.Blocks) != 1 {
				msg = fmt.Sprintf("BlocksListCallback: Expected block length at this point to be 1, got %d", len(hl.Blocks))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != state-1 {
				msg = fmt.Sprintf("HostListCallback: Expected block list revision at this point to be %d, got %d", state-1, hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}

		case 4, 5:
			if len(hl.Blocks) != 2 {
				msg = fmt.Sprintf("BlocksListCallback: Expected block length at this point to be 2, got %d", len(hl.Blocks))
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if hl.Revision != state-1 {
				msg = fmt.Sprintf("HostListCallback: Expected block list revision at this point to be %d, got %d", state-1, hl.Revision)
				fmt.Println(msg)
				errCh <- msg
				return
			}
			if state == 5 {
				// Here everything is ok!
				okCh <- "OK"
			}
		default:
			msg = fmt.Sprintf("HostListCallback: Did not expect HostListCallback to be called in state %d", state)
			errCh <- msg

		}

	})
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.IPAM.AllocateIP("addr1", "host1", "t1", "s1")
	if err != nil {
		t.Fatal(err)
	}
	_, err = client.IPAM.AllocateIP("addr2", "host1", "t1", "s1")
	if err != nil {
		t.Fatal(err)
	}
	_, err = client.IPAM.AllocateIP("addr3", "host1", "t1", "s1")
	if err != nil {
		t.Fatal(err)
	}
	_, err = client.IPAM.AllocateIP("addr4", "host1", "t1", "s1")
	if err != nil {
		t.Fatal(err)
	}
	for {
		select {
		case msg := <-errCh:
			t.Fatal(msg)
			break
		case <-okCh:
			return
		}
	}
}
*/

/*
func TestConcurrency(t *testing.T) {
	//	defer tearDown(t)
	client = initClient(t, "")

	barrier := make(chan int)
	cnt := 8
	locker, err := client.Store.NewLocker("/lock")
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < cnt; i++ {
		go func(i int) {
			fmt.Printf("%d %d Entered\n", i, getGID())
			defer func(i int) {
				fmt.Printf("%d %d Unlocking\n", i, getGID())
				locker.Unlock()
				fmt.Printf("%d %d Unlocked\n", i, getGID())
			}(i)
			fmt.Printf("%d %d Waiting for lock\n", i, getGID())
			locker.Lock()
			fmt.Printf("%d %d Got lock\n", i, getGID())
			val := fmt.Sprintf("Hello from %d %d", i, getGID())
			err := client.Store.Put(fmt.Sprintf("/test%d", i), []byte(val), nil)
			if err != nil {
				fmt.Println(err)
			}
			barrier <- 1
		}(i)
	}
	finishedCnt := 0

WAIT_FOR_FINISH:
	for {
		select {
		case <-barrier:
			finishedCnt++
			fmt.Printf("%d routines finished\n", finishedCnt)
			if finishedCnt == cnt {
				break WAIT_FOR_FINISH
			}
		}
	}
}
*/

type testcase struct {
	name string
	ipam *IPAM
	want interface{}
}

func loadTestFiles(name string, inFile string, outFile string) (testcase, error) {
	input, err := ioutil.ReadFile(inFile)
	if err != nil {
		return testcase{}, fmt.Errorf("error reading test input file: %s", err)
	}
	output, err := ioutil.ReadFile(outFile)
	if err != nil {
		return testcase{}, fmt.Errorf("error reading test output file: %s", err)
	}

	ipamState := &IPAM{}
	err = json.Unmarshal(input, ipamState)
	if err != nil {
		return testcase{}, fmt.Errorf("failed to unmarshal ipam information: %s", err)
	}
	topologyState := &api.TopologyUpdateRequest{}
	err = json.Unmarshal(output, topologyState)
	if err != nil {
		return testcase{}, fmt.Errorf("failed to unmarshal topology information: %s", err)
	}

	return testcase{name, ipamState, topologyState}, nil
}

func Test_getTopologyFromIPAMState(t *testing.T) {
	var testcases []testcase

	testfiles := map[string][]string{
		"multinetwork": {
			"testdata/TestTopologyGetInputMultiNetworks.json",
			"testdata/TestTopologyGetOutputMultiNetworks.json",
		},
		"kubeadm": {
			"testdata/TestTopologyGetInputKubeadm.json",
			"testdata/TestTopologyGetOutputKubeadm.json",
		},
	}

	for name, file := range testfiles {
		tc, err := loadTestFiles(name, file[0], file[1])
		if err != nil {
			t.Errorf("error loading test files: %s", err)
			continue
		}
		testcases = append(testcases, tc)
	}

	for _, tt := range testcases {
		t.Run(tt.name, func(t *testing.T) {
			got := getTopologyFromIPAMState(tt.ipam)
			gotTUR, ok := got.(*api.TopologyUpdateRequest)
			if !ok {
				t.Fatalf("error while fetching topology from IPAM: %v", got)
			}
			sortNetworks := func(i, j int) bool {
				return gotTUR.Networks[i].Name < gotTUR.Networks[j].Name
			}
			sortTopologies := func(i, j int) bool {
				return gotTUR.Topologies[i].Networks[0] < gotTUR.Topologies[j].Networks[0]
			}
			sort.SliceStable(gotTUR.Networks, sortNetworks)
			sort.SliceStable(gotTUR.Topologies, sortTopologies)

			wantTUR, ok := tt.want.(*api.TopologyUpdateRequest)
			if !ok {
				t.Fatalf("error while processing IPAM state: %v", tt.want)
			}
			sortNetworks = func(i, j int) bool {
				return wantTUR.Networks[i].Name < wantTUR.Networks[j].Name
			}
			sortTopologies = func(i, j int) bool {
				return wantTUR.Topologies[i].Networks[0] < wantTUR.Topologies[j].Networks[0]
			}
			sort.SliceStable(wantTUR.Networks, sortNetworks)
			sort.SliceStable(wantTUR.Topologies, sortTopologies)

			if !reflect.DeepEqual(gotTUR, wantTUR) {
				bodyGot, errGot := json.MarshalIndent(got, "", "\t")
				bodyWant, errWant := json.MarshalIndent(tt.want, "", "\t")
				if errGot == nil && errWant == nil {
					t.Errorf("getTopology() = \ngot(%s)\nwant(%s)",
						string(bodyGot), string(bodyWant))
				} else {
					t.Errorf("getTopology() = \ngot(%#v)\nwant(%#v)", got, tt.want)
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>package git_pipeline_test

import (
	"fmt"
	"net/http"
	"os/exec"
	"strings"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/cloudfoundry-incubator/garden/client"
	"github.com/cloudfoundry-incubator/garden/client/connection"
	"github.com/mgutz/ansi"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"

	"testing"
	"time"
)

// has ruby, curl
const guidServerRootfs = "/var/vcap/packages/bosh_deployment_resource"

// has git, curl
const gitServerRootfs = "/var/vcap/packages/git_resource"

var flyBin string

var (
	gardenClient garden.Client

	atcURL string

	pipelineName string
)

var _ = BeforeSuite(func() {
	// observed jobs taking ~1m30s, so set the timeout pretty high
	SetDefaultEventuallyTimeout(5 * time.Minute)

	// poll less frequently
	SetDefaultEventuallyPollingInterval(time.Second)

	var err error

	flyBin, err = gexec.Build("github.com/concourse/fly", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	gardenClient = client.New(connection.New("tcp", "10.244.15.2:7777"))
	Eventually(gardenClient.Ping).ShouldNot(HaveOccurred())

	atcURL = "http://10.244.15.2:8080"

	Eventually(errorPolling(atcURL)).ShouldNot(HaveOccurred())

	pipelineName = fmt.Sprintf("test-pipeline-%d", GinkgoParallelNode())
})

func TestGitPipeline(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Pipelines Suite")
}

func destroyPipeline() {
	destroyCmd := exec.Command("fly", "destroy-pipeline", pipelineName)

	stdin, err := destroyCmd.StdinPipe()
	Ω(err).ShouldNot(HaveOccurred())

	defer stdin.Close()

	destroy, err := gexec.Start(destroyCmd, GinkgoWriter, GinkgoWriter)
	Ω(err).ShouldNot(HaveOccurred())

	Eventually(destroy).Should(gbytes.Say("are you sure?"))

	fmt.Fprintln(stdin, "y")

	Eventually(destroy).Should(gexec.Exit(0))
}

func configurePipeline(argv ...string) {
	destroyPipeline()

	args := append([]string{
		"-t", atcURL,
		"configure",
		pipelineName,
		"--paused=false",
	}, argv...)

	configureCmd := exec.Command(flyBin, args...)

	stdin, err := configureCmd.StdinPipe()
	Ω(err).ShouldNot(HaveOccurred())

	defer stdin.Close()

	configure, err := gexec.Start(configureCmd, GinkgoWriter, GinkgoWriter)
	Ω(err).ShouldNot(HaveOccurred())

	Eventually(configure).Should(gbytes.Say("apply configuration?"))

	fmt.Fprintln(stdin, "y")

	Eventually(configure).Should(gexec.Exit(0))
}

func errorPolling(url string) func() error {
	return func() error {
		resp, err := http.Get(url)
		if err == nil {
			resp.Body.Close()
		}

		return err
	}
}

func flyWatch(jobName string) *gexec.Session {
	for {
		session := start(exec.Command(
			flyBin,
			"-t", atcURL,
			"watch",
			"-p", pipelineName,
			"-j", jobName,
		))

		<-session.Exited

		if session.ExitCode() == 1 {
			output := strings.TrimSpace(string(session.Err.Contents()))
			if output == "job has no builds" {
				// build hasn't started yet; keep polling
				time.Sleep(time.Second)
				continue
			}
		}

		return session
	}
}

func start(cmd *exec.Cmd) *gexec.Session {
	session, err := gexec.Start(
		cmd,
		gexec.NewPrefixedWriter(
			fmt.Sprintf("%s%s ", ansi.Color("[o]", "green"), ansi.Color("[fly]", "blue")),
			GinkgoWriter,
		),
		gexec.NewPrefixedWriter(
			fmt.Sprintf("%s%s ", ansi.Color("[e]", "red+bright"), ansi.Color("[fly]", "blue")),
			GinkgoWriter,
		),
	)
	Ω(err).ShouldNot(HaveOccurred())

	return session
}
<commit_msg>use retryable garden connection from atc<commit_after>package git_pipeline_test

import (
	"fmt"
	"net/http"
	"os/exec"
	"strings"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/cloudfoundry-incubator/garden/client"
	"github.com/cloudfoundry-incubator/garden/client/connection"
	"github.com/concourse/atc/worker"
	"github.com/mgutz/ansi"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-golang/clock"
	"github.com/pivotal-golang/lager/lagertest"

	"testing"
	"time"
)

// has ruby, curl
const guidServerRootfs = "/var/vcap/packages/bosh_deployment_resource"

// has git, curl
const gitServerRootfs = "/var/vcap/packages/git_resource"

var flyBin string

var (
	gardenClient garden.Client

	atcURL string

	pipelineName string
)

var _ = BeforeSuite(func() {
	// observed jobs taking ~1m30s, so set the timeout pretty high
	SetDefaultEventuallyTimeout(5 * time.Minute)

	// poll less frequently
	SetDefaultEventuallyPollingInterval(time.Second)

	var err error

	flyBin, err = gexec.Build("github.com/concourse/fly", "-race")
	Ω(err).ShouldNot(HaveOccurred())

	logger := lagertest.NewTestLogger("testflight")

	gardenClient = client.New(worker.RetryableConnection{
		Connection:  connection.New("tcp", "10.244.15.2:7777"),
		Logger:      logger.Session("garden-client"),
		Sleeper:     clock.NewClock(),
		RetryPolicy: worker.ExponentialRetryPolicy{Timeout: 5 * time.Minute},
	})
	Eventually(gardenClient.Ping).ShouldNot(HaveOccurred())

	atcURL = "http://10.244.15.2:8080"

	Eventually(errorPolling(atcURL)).ShouldNot(HaveOccurred())

	pipelineName = fmt.Sprintf("test-pipeline-%d", GinkgoParallelNode())
})

func TestGitPipeline(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Pipelines Suite")
}

func destroyPipeline() {
	destroyCmd := exec.Command("fly", "destroy-pipeline", pipelineName)

	stdin, err := destroyCmd.StdinPipe()
	Ω(err).ShouldNot(HaveOccurred())

	defer stdin.Close()

	destroy, err := gexec.Start(destroyCmd, GinkgoWriter, GinkgoWriter)
	Ω(err).ShouldNot(HaveOccurred())

	Eventually(destroy).Should(gbytes.Say("are you sure?"))

	fmt.Fprintln(stdin, "y")

	Eventually(destroy).Should(gexec.Exit(0))
}

func configurePipeline(argv ...string) {
	destroyPipeline()

	args := append([]string{
		"-t", atcURL,
		"configure",
		pipelineName,
		"--paused=false",
	}, argv...)

	configureCmd := exec.Command(flyBin, args...)

	stdin, err := configureCmd.StdinPipe()
	Ω(err).ShouldNot(HaveOccurred())

	defer stdin.Close()

	configure, err := gexec.Start(configureCmd, GinkgoWriter, GinkgoWriter)
	Ω(err).ShouldNot(HaveOccurred())

	Eventually(configure).Should(gbytes.Say("apply configuration?"))

	fmt.Fprintln(stdin, "y")

	Eventually(configure).Should(gexec.Exit(0))
}

func errorPolling(url string) func() error {
	return func() error {
		resp, err := http.Get(url)
		if err == nil {
			resp.Body.Close()
		}

		return err
	}
}

func flyWatch(jobName string) *gexec.Session {
	for {
		session := start(exec.Command(
			flyBin,
			"-t", atcURL,
			"watch",
			"-p", pipelineName,
			"-j", jobName,
		))

		<-session.Exited

		if session.ExitCode() == 1 {
			output := strings.TrimSpace(string(session.Err.Contents()))
			if output == "job has no builds" {
				// build hasn't started yet; keep polling
				time.Sleep(time.Second)
				continue
			}
		}

		return session
	}
}

func start(cmd *exec.Cmd) *gexec.Session {
	session, err := gexec.Start(
		cmd,
		gexec.NewPrefixedWriter(
			fmt.Sprintf("%s%s ", ansi.Color("[o]", "green"), ansi.Color("[fly]", "blue")),
			GinkgoWriter,
		),
		gexec.NewPrefixedWriter(
			fmt.Sprintf("%s%s ", ansi.Color("[e]", "red+bright"), ansi.Color("[fly]", "blue")),
			GinkgoWriter,
		),
	)
	Ω(err).ShouldNot(HaveOccurred())

	return session
}
<|endoftext|>


<commit_before>// Package s3 signs HTTP requests as prescribed in
// http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/RESTAuthentication.html.
package s3

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"io"
	"net/http"
	"sort"
	"strings"
)

var signParams = map[string]bool{
	"acl":                          true,
	"delete":                       true,
	"lifecycle":                    true,
	"location":                     true,
	"logging":                      true,
	"notification":                 true,
	"partNumber":                   true,
	"policy":                       true,
	"requestPayment":               true,
	"response-cache-control":       true,
	"response-content-disposition": true,
	"response-content-encoding":    true,
	"response-content-language":    true,
	"response-content-type":        true,
	"response-expires":             true,
	"torrent":                      true,
	"uploadId":                     true,
	"uploads":                      true,
	"versionId":                    true,
	"versioning":                   true,
	"versions":                     true,
	"website":                      true,
}

// Keys holds a set of Amazon Security Credentials.
type Keys struct {
	AccessKey string
	SecretKey string
}

// The default Service used by Sign.
var DefaultService = &Service{"amazonaws.com"}

// Sign signs an HTTP request with the given S3 keys.
//
// This function is shorthand for DefaultService.Sign(r, k).
func Sign(r *http.Request, k Keys) {
	DefaultService.Sign(r, k)
}

// Service represents an S3-compatible service.
type Service struct {
	Domain string // used to derive a bucket name from an http.Request
}

// Sign signs an HTTP request with the given S3 keys for use on service s.
func (s *Service) Sign(r *http.Request, k Keys) {
	h := hmac.New(sha1.New, []byte(k.SecretKey))
	s.writeSigData(h, r)
	sig := make([]byte, base64.StdEncoding.EncodedLen(h.Size()))
	base64.StdEncoding.Encode(sig, h.Sum(nil))
	r.Header.Set("Authorization", "AWS "+k.AccessKey+":"+string(sig))
}

func (s *Service) writeSigData(w io.Writer, r *http.Request) {
	w.Write([]byte(r.Method))
	w.Write([]byte{'\n'})
	w.Write([]byte(r.Header.Get("content-md5")))
	w.Write([]byte{'\n'})
	w.Write([]byte(r.Header.Get("content-type")))
	w.Write([]byte{'\n'})
	if _, ok := r.Header["X-Amz-Date"]; !ok {
		w.Write([]byte(r.Header.Get("date")))
	}
	w.Write([]byte{'\n'})
	writeAmzHeaders(w, r)
	s.writeResource(w, r)
}

func (s *Service) writeResource(w io.Writer, r *http.Request) {
	s.writeVhostBucket(w, r.Host)
	path := r.URL.RequestURI()
	if r.URL.RawQuery != "" {
		path = path[:len(path)-len(r.URL.RawQuery)-1]
	}
	w.Write([]byte(path))
	s.writeSubResource(w, r)
}

func (s *Service) writeVhostBucket(w io.Writer, host string) {
	if i := strings.Index(host, ":"); i != -1 {
		host = host[:i]
	}
	if !strings.HasSuffix(host, "."+s.Domain) {
		w.Write([]byte{'/'})
		w.Write([]byte(strings.ToLower(host)))
	} else if a := strings.Split(host, "."); len(a) > 3 {
		w.Write([]byte{'/'})
		w.Write([]byte(a[0]))
		for _, s := range a[1 : len(a)-3] { // omit .s3.amazonaws.com
			w.Write([]byte{'.'})
			w.Write([]byte(s))
		}
	}
}

func (s *Service) writeSubResource(w io.Writer, r *http.Request) {
	var a []string
	for k, vs := range r.URL.Query() {
		if signParams[k] {
			for _, v := range vs {
				if v == "" {
					a = append(a, k)
				} else {
					a = append(a, k+"="+v)
				}
			}
		}
	}
	sort.Strings(a)
	var p byte = '?'
	for _, s := range a {
		w.Write([]byte{p})
		w.Write([]byte(s))
		p = '&'
	}
}

func writeAmzHeaders(w io.Writer, r *http.Request) {
	var a []string
	for k, v := range r.Header {
		k = strings.ToLower(k)
		if strings.HasPrefix(k, "x-amz-") {
			a = append(a, k+":"+strings.Join(v, ","))
		}
	}
	sort.Strings(a)
	for _, h := range a {
		w.Write([]byte(h))
		w.Write([]byte{'\n'})
	}
}
<commit_msg>shorter initial sentence in godoc<commit_after>// Package s3 signs HTTP requests for Amazon S3.
//
// See
// http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/RESTAuthentication.html.
package s3

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"io"
	"net/http"
	"sort"
	"strings"
)

var signParams = map[string]bool{
	"acl":                          true,
	"delete":                       true,
	"lifecycle":                    true,
	"location":                     true,
	"logging":                      true,
	"notification":                 true,
	"partNumber":                   true,
	"policy":                       true,
	"requestPayment":               true,
	"response-cache-control":       true,
	"response-content-disposition": true,
	"response-content-encoding":    true,
	"response-content-language":    true,
	"response-content-type":        true,
	"response-expires":             true,
	"torrent":                      true,
	"uploadId":                     true,
	"uploads":                      true,
	"versionId":                    true,
	"versioning":                   true,
	"versions":                     true,
	"website":                      true,
}

// Keys holds a set of Amazon Security Credentials.
type Keys struct {
	AccessKey string
	SecretKey string
}

// The default Service used by Sign.
var DefaultService = &Service{"amazonaws.com"}

// Sign signs an HTTP request with the given S3 keys.
//
// This function is shorthand for DefaultService.Sign(r, k).
func Sign(r *http.Request, k Keys) {
	DefaultService.Sign(r, k)
}

// Service represents an S3-compatible service.
type Service struct {
	Domain string // used to derive a bucket name from an http.Request
}

// Sign signs an HTTP request with the given S3 keys for use on service s.
func (s *Service) Sign(r *http.Request, k Keys) {
	h := hmac.New(sha1.New, []byte(k.SecretKey))
	s.writeSigData(h, r)
	sig := make([]byte, base64.StdEncoding.EncodedLen(h.Size()))
	base64.StdEncoding.Encode(sig, h.Sum(nil))
	r.Header.Set("Authorization", "AWS "+k.AccessKey+":"+string(sig))
}

func (s *Service) writeSigData(w io.Writer, r *http.Request) {
	w.Write([]byte(r.Method))
	w.Write([]byte{'\n'})
	w.Write([]byte(r.Header.Get("content-md5")))
	w.Write([]byte{'\n'})
	w.Write([]byte(r.Header.Get("content-type")))
	w.Write([]byte{'\n'})
	if _, ok := r.Header["X-Amz-Date"]; !ok {
		w.Write([]byte(r.Header.Get("date")))
	}
	w.Write([]byte{'\n'})
	writeAmzHeaders(w, r)
	s.writeResource(w, r)
}

func (s *Service) writeResource(w io.Writer, r *http.Request) {
	s.writeVhostBucket(w, r.Host)
	path := r.URL.RequestURI()
	if r.URL.RawQuery != "" {
		path = path[:len(path)-len(r.URL.RawQuery)-1]
	}
	w.Write([]byte(path))
	s.writeSubResource(w, r)
}

func (s *Service) writeVhostBucket(w io.Writer, host string) {
	if i := strings.Index(host, ":"); i != -1 {
		host = host[:i]
	}
	if !strings.HasSuffix(host, "."+s.Domain) {
		w.Write([]byte{'/'})
		w.Write([]byte(strings.ToLower(host)))
	} else if a := strings.Split(host, "."); len(a) > 3 {
		w.Write([]byte{'/'})
		w.Write([]byte(a[0]))
		for _, s := range a[1 : len(a)-3] { // omit .s3.amazonaws.com
			w.Write([]byte{'.'})
			w.Write([]byte(s))
		}
	}
}

func (s *Service) writeSubResource(w io.Writer, r *http.Request) {
	var a []string
	for k, vs := range r.URL.Query() {
		if signParams[k] {
			for _, v := range vs {
				if v == "" {
					a = append(a, k)
				} else {
					a = append(a, k+"="+v)
				}
			}
		}
	}
	sort.Strings(a)
	var p byte = '?'
	for _, s := range a {
		w.Write([]byte{p})
		w.Write([]byte(s))
		p = '&'
	}
}

func writeAmzHeaders(w io.Writer, r *http.Request) {
	var a []string
	for k, v := range r.Header {
		k = strings.ToLower(k)
		if strings.HasPrefix(k, "x-amz-") {
			a = append(a, k+":"+strings.Join(v, ","))
		}
	}
	sort.Strings(a)
	for _, h := range a {
		w.Write([]byte(h))
		w.Write([]byte{'\n'})
	}
}
<|endoftext|>


<commit_before>package s3sig

import (
	"os"
	"http"
	"time"
	"sort"
	"bytes"
	"strings"
	"encoding/base64"
	"crypto/hmac"
)

var amzQueryParams = map[string]bool{
	"acl":                          true,
	"location":                     true,
	"logging":                      true,
	"notification":                 true,
	"partNumber":                   true,
	"policy":                       true,
	"requestPayment":               true,
	"torrent":                      true,
	"uploadId":                     true,
	"uploads":                      true,
	"versionId":                    true,
	"versioning":                   true,
	"versions":                     true,
	"website":                      true,
	"response-content-type":        true,
	"response-content-language":    true,
	"response-expires":             true,
	"response-cache-control":       true,
	"response-content-disposition": true,
	"response-content-encoding":    true,
}

func canonicalizedResource(url *http.URL) string {
	var res string

	// Strip any port declaration (443/80/8080/...)
	host := first(strings.Split(url.Host, ":", 2))

	if strings.HasSuffix(host, ".amazonaws.com") {
		// Hostname bucket style, ignore (s3-eu-west.|s3.)amazonaws.com
		parts := strings.Split(host, ".", -1)
		if len(parts) > 3 {
			res = res + "/" + strings.Join(parts[:len(parts)-3], ".")
		}
	} else if len(host) > 0 {
		// CNAME bucket style
		res = res + "/" + host
	} else {
		// Bucket as root element in path already
	}

	// RawPath will include the bucket if not in the host
	res = res + strings.Split(url.RawPath, "?", 2)[0]

	// Include a sorted list of query parameters that have
	// special meaning to aws.  These should stay decoded for
	// the canonical resource.
	var amz []string
	for key, values := range url.Query() {
		if amzQueryParams[key] {
			for _, value := range values {
				if value != "" {
					amz = append(amz, key+"="+value)
				} else {
					amz = append(amz, key)
				}
			}
		}
	}

	if len(amz) > 0 {
		sort.SortStrings(amz)
		res = res + "?" + strings.Join(amz, "&")
	}

	// All done.
	return res
}

func first(s []string) string {
	if len(s) > 0 {
		return s[0]
	}
	return ""
}

/*
	Creates the StringToSign string for either query string
	or Authorization header based authentication.
*/
func StringToSign(method string, url *http.URL, requestHeaders http.Header, expires string) string {
	// Positional headers are optional but should be captured
	var contentMD5, contentType, date, amzDate string
	var headers []string

	// Build the named, and capture the positional headers
	for name, values := range requestHeaders {
		name = strings.ToLower(name)

		switch name {
		case "date":
			date = first(values)
		case "content-type":
			contentType = first(values)
		case "content-md5":
			contentMD5 = first(values)
		default:
			if strings.HasPrefix(name, "x-amz-") {
				// Capture the x-amz-date header
				// Note: undefined behavior if there are more than
				// one of these headers
				if name == "x-amz-date" {
					amzDate = first(values)
				}

				// Assuming any rfc822 unfolding has happened already
				headers = append(headers, name+":"+strings.Join(values, ",")+"\n")
			}
		}
	}

	sort.SortStrings(headers)

	// overrideDate is used for query string "expires" auth
	// and is a unix timestamp
	switch {
	case expires != "":
		date = expires
	case amzDate != "":
		date = ""
	default:
		// Don't break referential transparency here by injecting
		// the date when the Date is empty.  Rather we assume the
		// caller knows what she is doing.
	}

	return method + "\n" +
		contentMD5 + "\n" +
		contentType + "\n" +
		date + "\n" +
		strings.Join(headers, "") +
		canonicalizedResource(url)
}

// Returns the signature to be used in the query string or Authorization header
func Signature(secret, toSign string) string {
	// Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of( YourSecretAccessKeyID, StringToSign ) ) );
	// Need to confirm what encoding go strings are when converted to []byte
	hmac := hmac.NewSHA1([]byte(secret))
	hmac.Write([]byte(toSign))

	var buf bytes.Buffer
	encoder := base64.NewEncoder(base64.StdEncoding, &buf)
	encoder.Write([]byte(hmac.Sum()))
	encoder.Close()

	return buf.String()
}

func Authorization(req *http.Request, key, secret string) string {
	return "AWS " + key + ":" + Signature(secret, StringToSign(req.Method, req.URL, req.Header, ""))
}

// Assumes no custom headers are sent so only needs access to a URL.
// If you plan on sending x-amz-* headers with a query string authorization
// you can use Signature(secret, StringToSign(url, headers, expires)) instead
// Returns an http.URL struct constructed from the Raw URL with the AWS
// query parameters appended at the end.
// Assumes any fragments are not included in url.Raw
func URL(url *http.URL, key, secret, method, expires string) (*http.URL, os.Error) {
	sig := Signature(secret, StringToSign(method, url, http.Header{}, expires))
	raw := url.Raw
	parts := strings.Split(raw, "?", 2)
	params := parts[1:]
	params = append(params, "AWSAccessKeyId="+key)
	params = append(params, "Expires="+expires)
	params = append(params, "Signature="+sig)
	signed := strings.Join(append(parts[:1], strings.Join(params, "&")), "?")

	return http.ParseURL(signed)
}

// Authorizes an http.Request pointer in place by in-place replacing the
// header of the provided request:
//
//	Authorization: AWS ACCOUNT SIGNATURE
//
// If the x-amz-date and Date headers are missing, this adds UTC current
// time in RFC1123 format inplace to the Date header:
//
//	Date: Mon, 02 Jan 2006 15:04:05 UTC
//
// If the Host does not appear in the req.URL, then it will be assigned
// from req.Host
func Authorize(req *http.Request, key, secret string) {
	var header string

	if req.URL.Host == "" {
		req.URL.Host = req.Host
	}

	if header = req.Header.Get("Date"); len(header) == 0 {
		if header = req.Header.Get("X-Amz-Date"); len(header) == 0 {
			req.Header.Set("Date", time.UTC().Format(time.RFC1123))
		}
	}

	req.Header.Set("Authorization", Authorization(req, key, secret))
}
<commit_msg>Simplify the base64 encoding with EncodeToString<commit_after>package s3sig

import (
	"os"
	"http"
	"time"
	"sort"
	"strings"
	"encoding/base64"
	"crypto/hmac"
)

var amzQueryParams = map[string]bool{
	"acl":                          true,
	"location":                     true,
	"logging":                      true,
	"notification":                 true,
	"partNumber":                   true,
	"policy":                       true,
	"requestPayment":               true,
	"torrent":                      true,
	"uploadId":                     true,
	"uploads":                      true,
	"versionId":                    true,
	"versioning":                   true,
	"versions":                     true,
	"website":                      true,
	"response-content-type":        true,
	"response-content-language":    true,
	"response-expires":             true,
	"response-cache-control":       true,
	"response-content-disposition": true,
	"response-content-encoding":    true,
}

func canonicalizedResource(url *http.URL) string {
	var res string

	// Strip any port declaration (443/80/8080/...)
	host := first(strings.Split(url.Host, ":", 2))

	if strings.HasSuffix(host, ".amazonaws.com") {
		// Hostname bucket style, ignore (s3-eu-west.|s3.)amazonaws.com
		parts := strings.Split(host, ".", -1)
		if len(parts) > 3 {
			res = res + "/" + strings.Join(parts[:len(parts)-3], ".")
		}
	} else if len(host) > 0 {
		// CNAME bucket style
		res = res + "/" + host
	} else {
		// Bucket as root element in path already
	}

	// RawPath will include the bucket if not in the host
	res = res + strings.Split(url.RawPath, "?", 2)[0]

	// Include a sorted list of query parameters that have
	// special meaning to aws.  These should stay decoded for
	// the canonical resource.
	var amz []string
	for key, values := range url.Query() {
		if amzQueryParams[key] {
			for _, value := range values {
				if value != "" {
					amz = append(amz, key+"="+value)
				} else {
					amz = append(amz, key)
				}
			}
		}
	}

	if len(amz) > 0 {
		sort.SortStrings(amz)
		res = res + "?" + strings.Join(amz, "&")
	}

	// All done.
	return res
}

func first(s []string) string {
	if len(s) > 0 {
		return s[0]
	}
	return ""
}

/*
	Creates the StringToSign string for either query string
	or Authorization header based authentication.
*/
func StringToSign(method string, url *http.URL, requestHeaders http.Header, expires string) string {
	// Positional headers are optional but should be captured
	var contentMD5, contentType, date, amzDate string
	var headers []string

	// Build the named, and capture the positional headers
	for name, values := range requestHeaders {
		name = strings.ToLower(name)

		switch name {
		case "date":
			date = first(values)
		case "content-type":
			contentType = first(values)
		case "content-md5":
			contentMD5 = first(values)
		default:
			if strings.HasPrefix(name, "x-amz-") {
				// Capture the x-amz-date header
				// Note: undefined behavior if there are more than
				// one of these headers
				if name == "x-amz-date" {
					amzDate = first(values)
				}

				// Assuming any rfc822 unfolding has happened already
				headers = append(headers, name+":"+strings.Join(values, ",")+"\n")
			}
		}
	}

	sort.SortStrings(headers)

	// overrideDate is used for query string "expires" auth
	// and is a unix timestamp
	switch {
	case expires != "":
		date = expires
	case amzDate != "":
		date = ""
	default:
		// Don't break referential transparency here by injecting
		// the date when the Date is empty.  Rather we assume the
		// caller knows what she is doing.
	}

	return method + "\n" +
		contentMD5 + "\n" +
		contentType + "\n" +
		date + "\n" +
		strings.Join(headers, "") +
		canonicalizedResource(url)
}

// Returns the signature to be used in the query string or Authorization header
func Signature(secret, toSign string) string {
	// Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of( YourSecretAccessKeyID, StringToSign ) ) );
	// Need to confirm what encoding go strings are when converted to []byte
	hmac := hmac.NewSHA1([]byte(secret))
	hmac.Write([]byte(toSign))

	return base64.StdEncoding.EncodeToString(hmac.Sum())
}

func Authorization(req *http.Request, key, secret string) string {
	return "AWS " + key + ":" + Signature(secret, StringToSign(req.Method, req.URL, req.Header, ""))
}

// Assumes no custom headers are sent so only needs access to a URL.
// If you plan on sending x-amz-* headers with a query string authorization
// you can use Signature(secret, StringToSign(url, headers, expires)) instead
// Returns an http.URL struct constructed from the Raw URL with the AWS
// query parameters appended at the end.
// Assumes any fragments are not included in url.Raw
func URL(url *http.URL, key, secret, method, expires string) (*http.URL, os.Error) {
	sig := Signature(secret, StringToSign(method, url, http.Header{}, expires))
	raw := url.Raw
	parts := strings.Split(raw, "?", 2)
	params := parts[1:]
	params = append(params, "AWSAccessKeyId="+key)
	params = append(params, "Expires="+expires)
	params = append(params, "Signature="+sig)
	signed := strings.Join(append(parts[:1], strings.Join(params, "&")), "?")

	return http.ParseURL(signed)
}

// Authorizes an http.Request pointer in place by in-place replacing the
// header of the provided request:
//
//	Authorization: AWS ACCOUNT SIGNATURE
//
// If the x-amz-date and Date headers are missing, this adds UTC current
// time in RFC1123 format inplace to the Date header:
//
//	Date: Mon, 02 Jan 2006 15:04:05 UTC
//
// If the Host does not appear in the req.URL, then it will be assigned
// from req.Host
func Authorize(req *http.Request, key, secret string) {
	var header string

	if req.URL.Host == "" {
		req.URL.Host = req.Host
	}

	if header = req.Header.Get("Date"); len(header) == 0 {
		if header = req.Header.Get("X-Amz-Date"); len(header) == 0 {
			req.Header.Set("Date", time.UTC().Format(time.RFC1123))
		}
	}

	req.Header.Set("Authorization", Authorization(req, key, secret))
}
<|endoftext|>