<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package features

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"k8s.io/contrib/mungegithub/github"
	"k8s.io/kubernetes/pkg/util/sets"
	"k8s.io/kubernetes/pkg/util/yaml"

	parseYaml "github.com/ghodss/yaml"
	"github.com/golang/glog"
	"github.com/spf13/cobra"
)

const (
	ownerFilename = "OWNERS" // file which contains approvers and reviewers
	// RepoFeatureName is how mungers should indicate this is required
	RepoFeatureName = "gitrepos"
)

type assignmentConfig struct {
	Assignees []string `json:assignees yaml:assignees`
	Approvers []string `json:approvers yaml:approvers`
	Reviewers []string `json:reviewers yaml:reviewers`
}

// RepoInfo provides information about users in OWNERS files in a git repo
type RepoInfo struct {
	BaseDir      string
	EnableMdYaml bool
	UseReviewers bool

	enabled    bool
	projectDir string
	approvers  map[string]sets.String
	reviewers  map[string]sets.String
	config     *github.Config
}

func init() {
	RegisterFeature(&RepoInfo{})
}

// Name is just going to return the name mungers use to request this feature
func (o *RepoInfo) Name() string {
	return RepoFeatureName
}

func (o *RepoInfo) walkFunc(path string, info os.FileInfo, err error) error {
	if err != nil {
		glog.Errorf("%v", err)
		return nil
	}
	filename := filepath.Base(path)
	if info.Mode().IsDir() {
		switch filename {
		case ".git":
			return filepath.SkipDir
		case "_output":
			return filepath.SkipDir
		}
	}
	if !info.Mode().IsRegular() {
		return nil
	}

	c := &assignmentConfig{}

	// '.md' files may contain assignees at the top of the file in a yaml header
	// Flag guarded because this is only enabled in some repos
	if o.EnableMdYaml && filename != ownerFilename && strings.HasSuffix(filename, "md") {
		// Parse the yaml header from the file if it exists and marshal into the config
		if err := decodeAssignmentConfig(path, c); err != nil {
			glog.Errorf("%v", err)
			return err
		}

		// Set assignees for this file using the relative path if they were found
		path, err = filepath.Rel(o.projectDir, path)
		if err != nil {
			glog.Errorf("Unable to find relative path between %q and %q: %v", o.projectDir, path, err)
			return err
		}
		o.approvers[path] = sets.NewString(c.Approvers...)
		o.approvers[path].Insert(c.Assignees...)
		o.reviewers[path] = sets.NewString(c.Reviewers...)
		return nil
	}

	if filename != ownerFilename {
		return nil
	}

	file, err := os.Open(path)
	if err != nil {
		glog.Errorf("%v", err)
		return nil
	}
	defer file.Close()

	if err := yaml.NewYAMLToJSONDecoder(file).Decode(c); err != nil {
		glog.Errorf("%v", err)
		return nil
	}

	path, err = filepath.Rel(o.projectDir, path)
	if err != nil {
		glog.Errorf("Unable to find relative path between %q and %q: %v", o.projectDir, path, err)
		return err
	}
	path = filepath.Dir(path)
	// Make the root explicitly / so its easy to distinguish. Nothing else is `/` anchored
	if path == "." {
		path = "/"
	}
	o.approvers[path] = sets.NewString(c.Approvers...)
	o.approvers[path].Insert(c.Assignees...)
	o.reviewers[path] = sets.NewString(c.Reviewers...)
	return nil
}

// decodeAssignmentConfig will parse the yaml header if it exists and unmarshal it into an assignmentConfig.
// If no yaml header is found, do nothing
// Returns an error if the file cannot be read or the yaml header is found but cannot be unmarshalled
var mdStructuredHeaderRegex = regexp.MustCompile("^---\n(.|\n)*\n---")

func decodeAssignmentConfig(path string, config *assignmentConfig) error {
	fileBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	// Parse the yaml header from the top of the file.  Will return an empty string if regex does not match.
	meta := mdStructuredHeaderRegex.FindString(string(fileBytes))

	// Unmarshal the yaml header into the config
	return parseYaml.Unmarshal([]byte(meta), &config)
}

func (o *RepoInfo) updateRepoUsers() error {
	out, err := o.GitCommand([]string{"pull"})
	if err != nil {
		glog.Errorf("Unable to run git pull:\n%s\n%v", string(out), err)
		return err
	}

	out, err = o.GitCommand([]string{"rev-parse", "HEAD"})
	if err != nil {
		glog.Errorf("Unable get sha of HEAD:\n%s\n%v", string(out), err)
		return err
	}
	sha := out

	o.approvers = map[string]sets.String{}
	o.reviewers = map[string]sets.String{}
	err = filepath.Walk(o.projectDir, o.walkFunc)
	if err != nil {
		glog.Errorf("Got error %v", err)
	}
	glog.Infof("Loaded config from %s:%s", o.projectDir, sha)
	glog.V(5).Infof("approvers: %v", o.approvers)
	glog.V(5).Infof("reviewers: %v", o.reviewers)
	return nil
}

// Initialize will initialize the munger
func (o *RepoInfo) Initialize(config *github.Config) error {
	o.enabled = true
	o.config = config
	o.projectDir = path.Join(o.BaseDir, o.config.Project)

	if len(o.BaseDir) == 0 {
		glog.Fatalf("--repo-dir is required with selected munger(s)")
	}
	finfo, err := os.Stat(o.BaseDir)
	if err != nil {
		return fmt.Errorf("Unable to stat --repo-dir: %v", err)
	}
	if !finfo.IsDir() {
		return fmt.Errorf("--repo-dir is not a directory")
	}

	// check if the cloned dir already exists, if yes, cleanup.
	if _, err := os.Stat(o.projectDir); !os.IsNotExist(err) {
		if err := o.cleanUp(o.projectDir); err != nil {
			return fmt.Errorf("Unable to remove old clone directory at %v: %v", o.projectDir, err)
		}
	}

	if cloneUrl, err := o.cloneRepo(); err != nil {
		return fmt.Errorf("Unable to clone %v: %v", cloneUrl, err)
	}
	return o.updateRepoUsers()
}

func (o *RepoInfo) cleanUp(path string) error {
	return os.RemoveAll(path)
}

func (o *RepoInfo) cloneRepo() (string, error) {
	cloneUrl := fmt.Sprintf("https://github.com/%s/%s.git", o.config.Org, o.config.Project)
	output, err := o.gitCommandDir([]string{"clone", cloneUrl, o.projectDir}, o.BaseDir)
	if err != nil {
		glog.Errorf("Failed to clone github repo: %s", output)
	}
	return cloneUrl, err
}

// EachLoop is called at the start of every munge loop
func (o *RepoInfo) EachLoop() error {
	if !o.enabled {
		return nil
	}
	_, err := o.GitCommand([]string{"remote", "update"})
	if err != nil {
		glog.Errorf("Unable to git remote update: %v", err)
	}
	return o.updateRepoUsers()
}

// AddFlags will add any request flags to the cobra `cmd`
func (o *RepoInfo) AddFlags(cmd *cobra.Command) {
	cmd.Flags().StringVar(&o.BaseDir, "repo-dir", "", "Path to perform checkout of repository")
	cmd.Flags().BoolVar(&o.EnableMdYaml, "enable-md-yaml", false, "If true, look for assignees in md yaml headers.")
	cmd.Flags().BoolVar(&o.UseReviewers, "use-reviewers", false, "Use \"reviewers\" rather than \"approvers\" for review")
}

// GitCommand will execute the git command with the `args` within the project directory.
func (o *RepoInfo) GitCommand(args []string) ([]byte, error) {
	return o.gitCommandDir(args, o.projectDir)
}

// GitCommandDir will execute the git command with the `args` within the 'dir' directory.
func (o *RepoInfo) gitCommandDir(args []string, cmdDir string) ([]byte, error) {
	cmd := exec.Command("git", args...)
	cmd.Dir = cmdDir
	return cmd.CombinedOutput()
}

// FindOwnersForPath returns the OWNERS file further down the tree for a file
func (o *RepoInfo) FindOwnersForPath(path string) string {
	d := path

	for {
		// special case the root
		if d == "" {
			d = "/"
		}
		_, ok := o.approvers[d]
		if ok {
			return d
		}
		if d == "/" {
			break
		}
		d = filepath.Dir(d)
		d = strings.TrimSuffix(d, "/")
	}
	return ""
}

// peopleForPath returns a set of users who are assignees to the
// requested file. The path variable should be a full path to a filename
// and not directory as the final directory will be discounted if enableMdYaml is true
// leafOnly indicates whether only the OWNERS deepest in the tree (closest to the file)
// should be returned or if all OWNERS in filepath should be returned
func peopleForPath(path string, people map[string]sets.String, leafOnly bool, enableMdYaml bool) sets.String {
	d := path
	if !enableMdYaml {
		// if path is a directory, this will remove the leaf directory
		d = filepath.Dir(path)
	}

	out := sets.NewString()
	for {
		// special case the root
		if d == "" {
			d = "/"
		}
		s, ok := people[d]
		if ok {
			out = out.Union(s)
			if leafOnly && out.Len() > 0 {
				break
			}
		}
		if d == "/" {
			break
		}
		d, _ = filepath.Split(d)
		d = strings.TrimSuffix(d, "/")
	}
	return out
}

// LeafApprovers returns a set of users who are the closest approvers to the
// requested file. If pkg/OWNERS has user1 and pkg/util/OWNERS has user2 this
// will only return user2 for the path pkg/util/sets/file.go
func (o *RepoInfo) LeafApprovers(path string) sets.String {
	return peopleForPath(path, o.approvers, true, o.EnableMdYaml)
}

// Approvers returns ALL of the users who are approvers for the
// requested file (including approvers in parent dirs' OWNERS).
// If pkg/OWNERS has user1 and pkg/util/OWNERS has user2 this
// will return both user1 and user2 for the path pkg/util/sets/file.go
func (o *RepoInfo) Approvers(path string) sets.String {
	return peopleForPath(path, o.approvers, false, o.EnableMdYaml)
}

// LeafReviewers returns a set of users who are the closest reviewers to the
// requested file. If pkg/OWNERS has user1 and pkg/util/OWNERS has user2 this
// will only return user2 for the path pkg/util/sets/file.go
func (o *RepoInfo) LeafReviewers(path string) sets.String {
	if !o.UseReviewers {
		return o.LeafApprovers(path)
	}
	return peopleForPath(path, o.reviewers, true, o.EnableMdYaml)
}

// Reviewers returns ALL of the users who are reviewers for the
// requested file (including reviewers in parent dirs' OWNERS).
// If pkg/OWNERS has user1 and pkg/util/OWNERS has user2 this
// will return both user1 and user2 for the path pkg/util/sets/file.go
func (o *RepoInfo) Reviewers(path string) sets.String {
	if !o.UseReviewers {
		return o.Approvers(path)
	}
	return peopleForPath(path, o.reviewers, false, o.EnableMdYaml)
}
<commit_msg>handling the . case<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package features

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"k8s.io/contrib/mungegithub/github"
	"k8s.io/kubernetes/pkg/util/sets"
	"k8s.io/kubernetes/pkg/util/yaml"

	parseYaml "github.com/ghodss/yaml"
	"github.com/golang/glog"
	"github.com/spf13/cobra"
)

const (
	ownerFilename = "OWNERS" // file which contains approvers and reviewers
	// RepoFeatureName is how mungers should indicate this is required
	RepoFeatureName = "gitrepos"
)

type assignmentConfig struct {
	Assignees []string `json:assignees yaml:assignees`
	Approvers []string `json:approvers yaml:approvers`
	Reviewers []string `json:reviewers yaml:reviewers`
}

// RepoInfo provides information about users in OWNERS files in a git repo
type RepoInfo struct {
	BaseDir      string
	EnableMdYaml bool
	UseReviewers bool

	enabled    bool
	projectDir string
	approvers  map[string]sets.String
	reviewers  map[string]sets.String
	config     *github.Config
}

func init() {
	RegisterFeature(&RepoInfo{})
}

// Name is just going to return the name mungers use to request this feature
func (o *RepoInfo) Name() string {
	return RepoFeatureName
}

func (o *RepoInfo) walkFunc(path string, info os.FileInfo, err error) error {
	if err != nil {
		glog.Errorf("%v", err)
		return nil
	}
	filename := filepath.Base(path)
	if info.Mode().IsDir() {
		switch filename {
		case ".git":
			return filepath.SkipDir
		case "_output":
			return filepath.SkipDir
		}
	}
	if !info.Mode().IsRegular() {
		return nil
	}

	c := &assignmentConfig{}

	// '.md' files may contain assignees at the top of the file in a yaml header
	// Flag guarded because this is only enabled in some repos
	if o.EnableMdYaml && filename != ownerFilename && strings.HasSuffix(filename, "md") {
		// Parse the yaml header from the file if it exists and marshal into the config
		if err := decodeAssignmentConfig(path, c); err != nil {
			glog.Errorf("%v", err)
			return err
		}

		// Set assignees for this file using the relative path if they were found
		path, err = filepath.Rel(o.projectDir, path)
		if err != nil {
			glog.Errorf("Unable to find relative path between %q and %q: %v", o.projectDir, path, err)
			return err
		}
		o.approvers[path] = sets.NewString(c.Approvers...)
		o.approvers[path].Insert(c.Assignees...)
		o.reviewers[path] = sets.NewString(c.Reviewers...)
		return nil
	}

	if filename != ownerFilename {
		return nil
	}

	file, err := os.Open(path)
	if err != nil {
		glog.Errorf("%v", err)
		return nil
	}
	defer file.Close()

	if err := yaml.NewYAMLToJSONDecoder(file).Decode(c); err != nil {
		glog.Errorf("%v", err)
		return nil
	}

	path, err = filepath.Rel(o.projectDir, path)
	if err != nil {
		glog.Errorf("Unable to find relative path between %q and %q: %v", o.projectDir, path, err)
		return err
	}
	path = filepath.Dir(path)
	// Make the root explicitly / so its easy to distinguish. Nothing else is `/` anchored
	if path == "." {
		path = "/"
	}
	o.approvers[path] = sets.NewString(c.Approvers...)
	o.approvers[path].Insert(c.Assignees...)
	o.reviewers[path] = sets.NewString(c.Reviewers...)
	return nil
}

// decodeAssignmentConfig will parse the yaml header if it exists and unmarshal it into an assignmentConfig.
// If no yaml header is found, do nothing
// Returns an error if the file cannot be read or the yaml header is found but cannot be unmarshalled
var mdStructuredHeaderRegex = regexp.MustCompile("^---\n(.|\n)*\n---")

func decodeAssignmentConfig(path string, config *assignmentConfig) error {
	fileBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	// Parse the yaml header from the top of the file.  Will return an empty string if regex does not match.
	meta := mdStructuredHeaderRegex.FindString(string(fileBytes))

	// Unmarshal the yaml header into the config
	return parseYaml.Unmarshal([]byte(meta), &config)
}

func (o *RepoInfo) updateRepoUsers() error {
	out, err := o.GitCommand([]string{"pull"})
	if err != nil {
		glog.Errorf("Unable to run git pull:\n%s\n%v", string(out), err)
		return err
	}

	out, err = o.GitCommand([]string{"rev-parse", "HEAD"})
	if err != nil {
		glog.Errorf("Unable get sha of HEAD:\n%s\n%v", string(out), err)
		return err
	}
	sha := out

	o.approvers = map[string]sets.String{}
	o.reviewers = map[string]sets.String{}
	err = filepath.Walk(o.projectDir, o.walkFunc)
	if err != nil {
		glog.Errorf("Got error %v", err)
	}
	glog.Infof("Loaded config from %s:%s", o.projectDir, sha)
	glog.V(5).Infof("approvers: %v", o.approvers)
	glog.V(5).Infof("reviewers: %v", o.reviewers)
	return nil
}

// Initialize will initialize the munger
func (o *RepoInfo) Initialize(config *github.Config) error {
	o.enabled = true
	o.config = config
	o.projectDir = path.Join(o.BaseDir, o.config.Project)

	if len(o.BaseDir) == 0 {
		glog.Fatalf("--repo-dir is required with selected munger(s)")
	}
	finfo, err := os.Stat(o.BaseDir)
	if err != nil {
		return fmt.Errorf("Unable to stat --repo-dir: %v", err)
	}
	if !finfo.IsDir() {
		return fmt.Errorf("--repo-dir is not a directory")
	}

	// check if the cloned dir already exists, if yes, cleanup.
	if _, err := os.Stat(o.projectDir); !os.IsNotExist(err) {
		if err := o.cleanUp(o.projectDir); err != nil {
			return fmt.Errorf("Unable to remove old clone directory at %v: %v", o.projectDir, err)
		}
	}

	if cloneUrl, err := o.cloneRepo(); err != nil {
		return fmt.Errorf("Unable to clone %v: %v", cloneUrl, err)
	}
	return o.updateRepoUsers()
}

func (o *RepoInfo) cleanUp(path string) error {
	return os.RemoveAll(path)
}

func (o *RepoInfo) cloneRepo() (string, error) {
	cloneUrl := fmt.Sprintf("https://github.com/%s/%s.git", o.config.Org, o.config.Project)
	output, err := o.gitCommandDir([]string{"clone", cloneUrl, o.projectDir}, o.BaseDir)
	if err != nil {
		glog.Errorf("Failed to clone github repo: %s", output)
	}
	return cloneUrl, err
}

// EachLoop is called at the start of every munge loop
func (o *RepoInfo) EachLoop() error {
	if !o.enabled {
		return nil
	}
	_, err := o.GitCommand([]string{"remote", "update"})
	if err != nil {
		glog.Errorf("Unable to git remote update: %v", err)
	}
	return o.updateRepoUsers()
}

// AddFlags will add any request flags to the cobra `cmd`
func (o *RepoInfo) AddFlags(cmd *cobra.Command) {
	cmd.Flags().StringVar(&o.BaseDir, "repo-dir", "", "Path to perform checkout of repository")
	cmd.Flags().BoolVar(&o.EnableMdYaml, "enable-md-yaml", false, "If true, look for assignees in md yaml headers.")
	cmd.Flags().BoolVar(&o.UseReviewers, "use-reviewers", false, "Use \"reviewers\" rather than \"approvers\" for review")
}

// GitCommand will execute the git command with the `args` within the project directory.
func (o *RepoInfo) GitCommand(args []string) ([]byte, error) {
	return o.gitCommandDir(args, o.projectDir)
}

// GitCommandDir will execute the git command with the `args` within the 'dir' directory.
func (o *RepoInfo) gitCommandDir(args []string, cmdDir string) ([]byte, error) {
	cmd := exec.Command("git", args...)
	cmd.Dir = cmdDir
	return cmd.CombinedOutput()
}

// FindOwnersForPath returns the OWNERS file further down the tree for a file
func (o *RepoInfo) FindOwnersForPath(path string) string {
	d := path

	for {
		// special case the root
		if d == "." || d == "" {
			d = "/"
		}
		_, ok := o.approvers[d]
		if ok {
			return d
		}
		if d == "/" {
			break
		}
		d = filepath.Dir(d)
		d = strings.TrimSuffix(d, "/")
	}
	return ""
}

// peopleForPath returns a set of users who are assignees to the
// requested file. The path variable should be a full path to a filename
// and not directory as the final directory will be discounted if enableMdYaml is true
// leafOnly indicates whether only the OWNERS deepest in the tree (closest to the file)
// should be returned or if all OWNERS in filepath should be returned
func peopleForPath(path string, people map[string]sets.String, leafOnly bool, enableMdYaml bool) sets.String {
	d := path
	if !enableMdYaml {
		// if path is a directory, this will remove the leaf directory
		d = filepath.Dir(path)
	}

	out := sets.NewString()
	for {
		// special case the root
		if d == "" {
			d = "/"
		}
		s, ok := people[d]
		if ok {
			out = out.Union(s)
			if leafOnly && out.Len() > 0 {
				break
			}
		}
		if d == "/" {
			break
		}
		d, _ = filepath.Split(d)
		d = strings.TrimSuffix(d, "/")
	}
	return out
}

// LeafApprovers returns a set of users who are the closest approvers to the
// requested file. If pkg/OWNERS has user1 and pkg/util/OWNERS has user2 this
// will only return user2 for the path pkg/util/sets/file.go
func (o *RepoInfo) LeafApprovers(path string) sets.String {
	return peopleForPath(path, o.approvers, true, o.EnableMdYaml)
}

// Approvers returns ALL of the users who are approvers for the
// requested file (including approvers in parent dirs' OWNERS).
// If pkg/OWNERS has user1 and pkg/util/OWNERS has user2 this
// will return both user1 and user2 for the path pkg/util/sets/file.go
func (o *RepoInfo) Approvers(path string) sets.String {
	return peopleForPath(path, o.approvers, false, o.EnableMdYaml)
}

// LeafReviewers returns a set of users who are the closest reviewers to the
// requested file. If pkg/OWNERS has user1 and pkg/util/OWNERS has user2 this
// will only return user2 for the path pkg/util/sets/file.go
func (o *RepoInfo) LeafReviewers(path string) sets.String {
	if !o.UseReviewers {
		return o.LeafApprovers(path)
	}
	return peopleForPath(path, o.reviewers, true, o.EnableMdYaml)
}

// Reviewers returns ALL of the users who are reviewers for the
// requested file (including reviewers in parent dirs' OWNERS).
// If pkg/OWNERS has user1 and pkg/util/OWNERS has user2 this
// will return both user1 and user2 for the path pkg/util/sets/file.go
func (o *RepoInfo) Reviewers(path string) sets.String {
	if !o.UseReviewers {
		return o.Approvers(path)
	}
	return peopleForPath(path, o.reviewers, false, o.EnableMdYaml)
}
<|endoftext|>


<commit_before>// This generates the protocol buffer code in go for the v1beta1 proto spec.

//go:generate rm -rf grafeas_go_proto
//go:generate mkdir grafeas_go_proto
//go:generate -command protoc ../../protoc/bin/protoc -I ../../ -I ./ -I ../../vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis -I ../../vendor/github.com/grpc-ecosystem/grpc-gateway -I ../../vendor/github.com/googleapis/googleapis --go_out=plugins=grpc,paths=source_relative:.  --grpc-gateway_out=logtostderr=true,paths=source_relative:.
//go:generate protoc attestation.proto
//go:generate mv attestation.pb.go grafeas_go_proto
//go:generate protoc common.proto
//go:generate mv common.pb.go grafeas_go_proto
//go:generate protoc deployment.proto
//go:generate mv deployment.pb.go grafeas_go_proto
//go:generate protoc grafeas.proto
//go:generate mv grafeas.pb.go grafeas_go_proto
//go:generate mv grafeas.pb.gw.go grafeas_go_proto
//go:generate protoc package.proto
//go:generate mv package.pb.go grafeas_go_proto
//go:generate protoc provenance.proto
//go:generate mv provenance.pb.go grafeas_go_proto
//go:generate protoc build.proto
//go:generate mv build.pb.go grafeas_go_proto
//go:generate protoc cvss.proto
//go:generate mv cvss.pb.go grafeas_go_proto
//go:generate protoc discovery.proto
//go:generate mv discovery.pb.go grafeas_go_proto
//go:generate protoc image.proto
//go:generate mv image.pb.go grafeas_go_proto
//go:generate protoc vulnerability.proto
//go:generate mv vulnerability.pb.go grafeas_go_proto
package v1
<commit_msg>Fix v1 generate comment to refer to v1 not v1beta1<commit_after>// This generates the protocol buffer code in go for the v1 proto spec.

//go:generate rm -rf grafeas_go_proto
//go:generate mkdir grafeas_go_proto
//go:generate -command protoc ../../protoc/bin/protoc -I ../../ -I ./ -I ../../vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis -I ../../vendor/github.com/grpc-ecosystem/grpc-gateway -I ../../vendor/github.com/googleapis/googleapis --go_out=plugins=grpc,paths=source_relative:.  --grpc-gateway_out=logtostderr=true,paths=source_relative:.
//go:generate protoc attestation.proto
//go:generate mv attestation.pb.go grafeas_go_proto
//go:generate protoc common.proto
//go:generate mv common.pb.go grafeas_go_proto
//go:generate protoc deployment.proto
//go:generate mv deployment.pb.go grafeas_go_proto
//go:generate protoc grafeas.proto
//go:generate mv grafeas.pb.go grafeas_go_proto
//go:generate mv grafeas.pb.gw.go grafeas_go_proto
//go:generate protoc package.proto
//go:generate mv package.pb.go grafeas_go_proto
//go:generate protoc provenance.proto
//go:generate mv provenance.pb.go grafeas_go_proto
//go:generate protoc build.proto
//go:generate mv build.pb.go grafeas_go_proto
//go:generate protoc cvss.proto
//go:generate mv cvss.pb.go grafeas_go_proto
//go:generate protoc discovery.proto
//go:generate mv discovery.pb.go grafeas_go_proto
//go:generate protoc image.proto
//go:generate mv image.pb.go grafeas_go_proto
//go:generate protoc vulnerability.proto
//go:generate mv vulnerability.pb.go grafeas_go_proto
package v1
<|endoftext|>


<commit_before>package entity

import (
	"time"
)

type User struct {
	UserName string `json:"username"`
	PassWord string `json:"password"`
	Start    bool   `json:"start"`
	Trigger  int64  `json:"trigger"`
	Date     time.Time
}

type Task struct {
	Users []*User `json:"users"`
	Start bool    `json:"start"`
	Size  int
}
<commit_msg>add cancel task<commit_after>package entity

import (
	"time"
)

type User struct {
	UserName string `json:"username"`
	PassWord string `json:"password"`
	Start    bool   `json:"start"`
	Trigger  int64  `json:"trigger"`
	Date     time.Time
}

type Task struct {
	Start  bool     `json:"start"`
	Users  []*User  `json:"users"`
	Cancel []string `json:"cancel"`
	Size   int
}
<|endoftext|>


<commit_before>// Package export handles exporting parts of the repo to other directories.
// This is useful if, for example, one wanted to separate out part of
// their repo with all dependencies.
package export

import (
	"os"
	"path"
	"strings"

	"github.com/thought-machine/please/src/cli/logging"

	"github.com/thought-machine/please/src/core"
	"github.com/thought-machine/please/src/fs"
	"github.com/thought-machine/please/src/gc"
	"github.com/thought-machine/please/src/parse"
)

var log = logging.Log

// ToDir exports a set of targets to the given directory.
// It dies on any errors.
func ToDir(state *core.BuildState, dir string, targets []core.BuildLabel) {
	done := map[*core.BuildTarget]bool{}
	for _, target := range targets {
		export(state.Graph, dir, state.Graph.TargetOrDie(target), done)
	}
	// Now write all the build files
	packages := map[*core.Package]bool{}
	for target := range done {
		packages[state.Graph.PackageOrDie(target.Label)] = true
	}
	for pkg := range packages {
		if pkg.Name == parse.InternalPackageName {
			continue // This isn't a real package to be copied
		}
		dest := path.Join(dir, pkg.Filename)
		if err := fs.RecursiveCopy(pkg.Filename, dest, 0); err != nil {
			log.Fatalf("Failed to copy BUILD file %s: %s\n", pkg.Filename, err)
		}
		// Now rewrite the unused targets out of it
		victims := []string{}
		for _, target := range pkg.AllTargets() {
			if !done[target] && !target.HasParent() {
				victims = append(victims, target.Label.Name)
			}
		}
		if err := gc.RewriteFile(state, dest, victims); err != nil {
			log.Fatalf("Failed to rewrite BUILD file: %s\n", err)
		}
	}
	// Write any preloaded build defs as well; preloaded subincludes should be fine though.
	for _, preload := range state.Config.Parse.PreloadBuildDefs {
		if err := fs.RecursiveCopy(preload, path.Join(dir, preload), 0); err != nil {
			log.Fatalf("Failed to copy preloaded build def %s: %s", preload, err)
		}
	}
}

// export implements the logic of ToDir, but prevents repeating targets.
func export(graph *core.BuildGraph, dir string, target *core.BuildTarget, done map[*core.BuildTarget]bool) {
	if done[target] {
		return
	}
	for _, src := range append(target.AllSources(), target.AllData()...) {
		if _, ok := src.Label(); !ok { // We'll handle these dependencies later
			for _, p := range src.FullPaths(graph) {
				if !strings.HasPrefix(p, "/") { // Don't copy system file deps.
					if err := fs.RecursiveCopy(p, path.Join(dir, p), 0); err != nil {
						log.Fatalf("Error copying file: %s\n", err)
					}
				}
			}
		}
	}
	done[target] = true
	for _, dep := range target.Dependencies() {
		export(graph, dir, dep, done)
	}
	for _, subinclude := range graph.PackageOrDie(target.Label).Subincludes {
		export(graph, dir, graph.TargetOrDie(subinclude), done)
	}
	if parent := target.Parent(graph); parent != nil && parent != target {
		export(graph, dir, parent, done)
	}
}

// Outputs exports the outputs of a target.
func Outputs(state *core.BuildState, dir string, targets []core.BuildLabel) {
	for _, label := range targets {
		target := state.Graph.TargetOrDie(label)
		for _, out := range target.Outputs() {
			fullPath := path.Join(dir, out)
			outDir := path.Dir(fullPath)
			if err := os.MkdirAll(outDir, core.DirPermissions); err != nil {
				log.Fatalf("Failed to create export dir %s: %s", outDir, err)
			}
			if err := fs.RecursiveCopy(path.Join(target.OutDir(), out), fullPath, target.OutMode()|0200); err != nil {
				log.Fatalf("Failed to copy export file: %s", err)
			}
		}
	}
}
<commit_msg>Export the preloaded subincludes too (#2397)<commit_after>// Package export handles exporting parts of the repo to other directories.
// This is useful if, for example, one wanted to separate out part of
// their repo with all dependencies.
package export

import (
	"os"
	"path"
	"strings"

	"github.com/thought-machine/please/src/cli/logging"

	"github.com/thought-machine/please/src/core"
	"github.com/thought-machine/please/src/fs"
	"github.com/thought-machine/please/src/gc"
	"github.com/thought-machine/please/src/parse"
)

var log = logging.Log

// ToDir exports a set of targets to the given directory.
// It dies on any errors.
func ToDir(state *core.BuildState, dir string, targets []core.BuildLabel) {
	done := map[*core.BuildTarget]bool{}
	for _, target := range append(state.Config.Parse.PreloadSubincludes, targets...) {
		export(state.Graph, dir, state.Graph.TargetOrDie(target), done)
	}
	// Now write all the build files
	packages := map[*core.Package]bool{}
	for target := range done {
		packages[state.Graph.PackageOrDie(target.Label)] = true
	}
	for pkg := range packages {
		if pkg.Name == parse.InternalPackageName {
			continue // This isn't a real package to be copied
		}
		dest := path.Join(dir, pkg.Filename)
		if err := fs.RecursiveCopy(pkg.Filename, dest, 0); err != nil {
			log.Fatalf("Failed to copy BUILD file %s: %s\n", pkg.Filename, err)
		}
		// Now rewrite the unused targets out of it
		victims := []string{}
		for _, target := range pkg.AllTargets() {
			if !done[target] && !target.HasParent() {
				victims = append(victims, target.Label.Name)
			}
		}
		if err := gc.RewriteFile(state, dest, victims); err != nil {
			log.Fatalf("Failed to rewrite BUILD file: %s\n", err)
		}
	}
	// Write any preloaded build defs as well; preloaded subincludes should be fine though.
	for _, preload := range state.Config.Parse.PreloadBuildDefs {
		if err := fs.RecursiveCopy(preload, path.Join(dir, preload), 0); err != nil {
			log.Fatalf("Failed to copy preloaded build def %s: %s", preload, err)
		}
	}
}

// export implements the logic of ToDir, but prevents repeating targets.
func export(graph *core.BuildGraph, dir string, target *core.BuildTarget, done map[*core.BuildTarget]bool) {
	// We want to export the package that made this subrepo available
	if target.Subrepo != nil {
		target = target.Subrepo.Target
	}
	if done[target] {
		return
	}
	for _, src := range append(target.AllSources(), target.AllData()...) {
		if _, ok := src.Label(); !ok { // We'll handle these dependencies later
			for _, p := range src.FullPaths(graph) {
				if !strings.HasPrefix(p, "/") { // Don't copy system file deps.
					if err := fs.RecursiveCopy(p, path.Join(dir, p), 0); err != nil {
						log.Fatalf("Error copying file: %s\n", err)
					}
				}
			}
		}
	}
	done[target] = true
	for _, dep := range target.Dependencies() {
		export(graph, dir, dep, done)
	}
	for _, subinclude := range graph.PackageOrDie(target.Label).Subincludes {
		export(graph, dir, graph.TargetOrDie(subinclude), done)
	}
	if parent := target.Parent(graph); parent != nil && parent != target {
		export(graph, dir, parent, done)
	}
}

// Outputs exports the outputs of a target.
func Outputs(state *core.BuildState, dir string, targets []core.BuildLabel) {
	for _, label := range targets {
		target := state.Graph.TargetOrDie(label)
		for _, out := range target.Outputs() {
			fullPath := path.Join(dir, out)
			outDir := path.Dir(fullPath)
			if err := os.MkdirAll(outDir, core.DirPermissions); err != nil {
				log.Fatalf("Failed to create export dir %s: %s", outDir, err)
			}
			if err := fs.RecursiveCopy(path.Join(target.OutDir(), out), fullPath, target.OutMode()|0200); err != nil {
				log.Fatalf("Failed to copy export file: %s", err)
			}
		}
	}
}
<|endoftext|>


<commit_before>package phonenumber

import (
	"math/rand"
	"time"
)

const (
	fakeLineNumberMin = 100
	fakeLineNumberMax = 199
)

type FakeNumberGenerator struct {
	AreaCodeToGeo AreaCodeToGeo
	AreaCodes     []int
	Rand          *rand.Rand
}

func NewFakeNumberGenerator(a2g AreaCodeToGeo) FakeNumberGenerator {
	fng := FakeNumberGenerator{
		AreaCodeToGeo: a2g,
		AreaCodes:     a2g.AreaCodes(),
		Rand:          rand.New(rand.NewSource(time.Now().Unix())),
	}
	return fng
}

// RandomAreaCode generates a random area code.
func (fng *FakeNumberGenerator) RandomAreaCode() int {
	return fng.AreaCodes[fng.Rand.Intn(len(fng.AreaCodes))]
}

// RandomLineNumber generates a random line number
func (fng *FakeNumberGenerator) RandomLineNumber() int {
	return fng.Rand.Intn(fakeLineNumberMax-fakeLineNumberMin) + fakeLineNumberMin
}

// RandomLocalNumberUS returns a US E.164 number
// AreaCode + Prefix + Line Number
func (fng *FakeNumberGenerator) RandomLocalNumberUS() int {
	ac := fng.RandomAreaCode()
	ln := fng.RandomLineNumber()
	return 10000000000 + (ac * 10000000) + (5550000) + ln
}

// RandomLocalNumberUS returns a US E.164 number
// AreaCode + Prefix + Line Number
func (fng *FakeNumberGenerator) RandomLocalNumberUSUnique(set map[int]int) (int, map[int]int) {
	try := fng.RandomLocalNumberUS()
	_, ok := set[try]
	for ok {
		try := fng.RandomLocalNumberUS()
		_, ok = set[try]
	}
	set[try] = 1
	return try, set
}
<commit_msg>remove dependency<commit_after>package phonenumber

import (
	"math/rand"
	"time"
)

const (
	fakeLineNumberMin = 100
	fakeLineNumberMax = 199
)

type FakeNumberGenerator struct {
	AreaCodes []int
	Rand      *rand.Rand
}

func NewFakeNumberGenerator(areacodes []int) FakeNumberGenerator {
	fng := FakeNumberGenerator{
		AreaCodes: areacodes,
		Rand:      rand.New(rand.NewSource(time.Now().Unix())),
	}
	return fng
}

// RandomAreaCode generates a random area code.
func (fng *FakeNumberGenerator) RandomAreaCode() int {
	return fng.AreaCodes[fng.Rand.Intn(len(fng.AreaCodes))]
}

// RandomLineNumber generates a random line number
func (fng *FakeNumberGenerator) RandomLineNumber() int {
	return fng.Rand.Intn(fakeLineNumberMax-fakeLineNumberMin) + fakeLineNumberMin
}

// RandomLocalNumberUS returns a US E.164 number
// AreaCode + Prefix + Line Number
func (fng *FakeNumberGenerator) RandomLocalNumberUS() int {
	ac := fng.RandomAreaCode()
	ln := fng.RandomLineNumber()
	return 10000000000 + (ac * 10000000) + (5550000) + ln
}

// RandomLocalNumberUS returns a US E.164 number
// AreaCode + Prefix + Line Number
func (fng *FakeNumberGenerator) RandomLocalNumberUSUnique(set map[int]int) (int, map[int]int) {
	try := fng.RandomLocalNumberUS()
	_, ok := set[try]
	for ok {
		try := fng.RandomLocalNumberUS()
		_, ok = set[try]
	}
	set[try] = 1
	return try, set
}
<|endoftext|>


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

package main

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

	"cloud.google.com/go/profiler"
	"contrib.go.opencensus.io/exporter/stackdriver"
	"github.com/gorilla/mux"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"go.opencensus.io/plugin/ocgrpc"
	"go.opencensus.io/stats/view"
	"go.opencensus.io/trace"

	// OTel Metric
	"go.opentelemetry.io/otel/api/metric"
	metricstdout "go.opentelemetry.io/otel/exporters/metric/stdout"
	"go.opentelemetry.io/otel/instrumentation/othttp"
	"go.opentelemetry.io/otel/sdk/metric/controller/push"

	// OTel Trace
	// OTel -> GCP Trace direct exporter for go
	texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
	"go.opentelemetry.io/otel/api/global"
	"go.opentelemetry.io/otel/api/standard"
	"go.opentelemetry.io/otel/instrumentation/grpctrace"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	"go.opentelemetry.io/otel/sdk/resource"

	"google.golang.org/grpc"
)

const (
	port            = "8080"
	defaultCurrency = "USD"
	cookieMaxAge    = 60 * 60 * 48

	cookiePrefix    = "shop_"
	cookieSessionID = cookiePrefix + "session-id"
	cookieCurrency  = cookiePrefix + "currency"
)

var (
	whitelistedCurrencies = map[string]bool{
		"USD": true,
		"EUR": true,
		"CAD": true,
		"JPY": true,
		"GBP": true,
		"TRY": true}
		// Custom Metrics for User Dashboard
		// TODO: use automatic metrics collection when Views API available in OpenTelemetry
		// TODO: remove these after automatically collected
		http_request_count metric.Int64Counter
		http_response_errors metric.Int64Counter
		http_request_latency metric.Int64ValueRecorder
)

type ctxKeySessionID struct{}

type frontendServer struct {
	productCatalogSvcAddr string
	productCatalogSvcConn *grpc.ClientConn

	currencySvcAddr string
	currencySvcConn *grpc.ClientConn

	cartSvcAddr string
	cartSvcConn *grpc.ClientConn

	recommendationSvcAddr string
	recommendationSvcConn *grpc.ClientConn

	checkoutSvcAddr string
	checkoutSvcConn *grpc.ClientConn

	shippingSvcAddr string
	shippingSvcConn *grpc.ClientConn

	adSvcAddr string
	adSvcConn *grpc.ClientConn
}

func main() {
	ctx := context.Background()
	log := logrus.New()
	log.Level = logrus.DebugLevel
	log.Formatter = &logrus.JSONFormatter{
		FieldMap: logrus.FieldMap{
			logrus.FieldKeyTime:  "timestamp",
			logrus.FieldKeyLevel: "severity",
			logrus.FieldKeyMsg:   "message",
		},
		TimestampFormat: time.RFC3339Nano,
	}
	log.Out = os.Stdout

	controller := initMetricsExporter(log)
	defer controller.Stop()

	go initProfiling(log, "frontend", "1.0.0")
	go initTelemetry(log)

	// TODO: register views when OpenTelemetry Views API is available
	meter := controller.Provider().Meter("hipstershop/frontend")
	// TODO: use automatic default metrics collection and remove custom metrics
	http_request_count = metric.Must(meter).NewInt64Counter("http_request_count")
	http_response_errors = metric.Must(meter).NewInt64Counter("http_response_errors")
	http_request_latency = metric.Must(meter).NewInt64ValueRecorder("http_request_latency")
	tracer := global.TraceProvider().Tracer("hipstershop/frontend")
	ctx, span := tracer.Start(ctx, "root")
	defer span.End()

	srvPort := port
	if os.Getenv("PORT") != "" {
		srvPort = os.Getenv("PORT")
	}
	addr := os.Getenv("LISTEN_ADDR")
	svc := new(frontendServer)
	mustMapEnv(&svc.productCatalogSvcAddr, "PRODUCT_CATALOG_SERVICE_ADDR")
	mustMapEnv(&svc.currencySvcAddr, "CURRENCY_SERVICE_ADDR")
	mustMapEnv(&svc.cartSvcAddr, "CART_SERVICE_ADDR")
	mustMapEnv(&svc.recommendationSvcAddr, "RECOMMENDATION_SERVICE_ADDR")
	mustMapEnv(&svc.checkoutSvcAddr, "CHECKOUT_SERVICE_ADDR")
	mustMapEnv(&svc.shippingSvcAddr, "SHIPPING_SERVICE_ADDR")
	mustMapEnv(&svc.adSvcAddr, "AD_SERVICE_ADDR")

	mustConnGRPC(ctx, &svc.currencySvcConn, svc.currencySvcAddr)
	mustConnGRPC(ctx, &svc.productCatalogSvcConn, svc.productCatalogSvcAddr)
	mustConnGRPC(ctx, &svc.cartSvcConn, svc.cartSvcAddr)
	mustConnGRPC(ctx, &svc.recommendationSvcConn, svc.recommendationSvcAddr)
	mustConnGRPC(ctx, &svc.shippingSvcConn, svc.shippingSvcAddr)
	mustConnGRPC(ctx, &svc.checkoutSvcConn, svc.checkoutSvcAddr)
	mustConnGRPC(ctx, &svc.adSvcConn, svc.adSvcAddr)

	r := mux.NewRouter()
	r.HandleFunc("/", svc.homeHandler).Methods(http.MethodGet, http.MethodHead)
	r.HandleFunc("/product/{id}", svc.productHandler).Methods(http.MethodGet, http.MethodHead)
	r.HandleFunc("/cart", svc.viewCartHandler).Methods(http.MethodGet, http.MethodHead)
	r.HandleFunc("/cart", svc.addToCartHandler).Methods(http.MethodPost)
	r.HandleFunc("/cart/empty", svc.emptyCartHandler).Methods(http.MethodPost)
	r.HandleFunc("/setCurrency", svc.setCurrencyHandler).Methods(http.MethodPost)
	r.HandleFunc("/logout", svc.logoutHandler).Methods(http.MethodGet)
	r.HandleFunc("/cart/checkout", svc.placeOrderHandler).Methods(http.MethodPost)
	r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))
	r.HandleFunc("/robots.txt", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "User-agent: *\nDisallow: /") })
	r.HandleFunc("/_healthz", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "ok") })

	var handler http.Handler = othttp.NewHandler(r, "frontend", // OpenTelemetry HTTP wrapper
		othttp.WithMessageEvents(othttp.ReadEvents, othttp.WriteEvents)) // Uses global meter and tracer
	handler = &logHandler{log: log, next: handler} // add logging
	handler = ensureSessionID(handler)             // add session ID

	log.Infof("starting server on " + addr + ":" + srvPort)
	log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler))
}

// TODO: remove this after full conversion to OpenTelemetry
func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) {
	view.SetReportingPeriod(60 * time.Second)
	view.RegisterExporter(exporter)
	if err := view.Register(ocgrpc.DefaultClientViews...); err != nil {
		log.Warn("Error registering grpc default client views")
	} else {
		log.Info("Registered grpc default client views")
	}
}

// Initialize OpenTelemetry Metrics exporter
func initMetricsExporter(log logrus.FieldLogger) *push.Controller {
	// TODO: export to Cloud Monitoring instead of stdout
	pusher, err := metricstdout.InstallNewPipeline(metricstdout.Config{
		PrettyPrint: false,
	})
	if err != nil {
		log.Panicf("failed to initialize metric stdout exporter %v", err)
	}
	return pusher
}

// TODO: remove this after full conversion to OpenTelemetry
func initOpenCensus(log logrus.FieldLogger) {
	// TODO(ahmetb) this method is duplicated in other microservices using Go
	// since they are not sharing packages.
	for i := 1; i <= 3; i++ {
		log = log.WithField("retry", i)
		exporter, err := stackdriver.NewExporter(stackdriver.Options{})
		if err != nil {
			log.Warnf("failed to initialize stackdriver exporter: %+v", err)
		} else {
			trace.RegisterExporter(exporter)
			log.Info("registered stackdriver tracing")

			// Register the views to collect server stats.
			initStats(log, exporter)
			return
		}
		d := time.Second * 20 * time.Duration(i)
		log.Debugf("sleeping %v to retry initializing stackdriver exporter", d)
		time.Sleep(d)
	}
	log.Warn("could not initialize stackdriver exporter after retrying, giving up")
}

// Initialize Telemetry collection (Tracing, Metrics/Stats) with OpenCensus and OpenTelemetry
func initTelemetry(log logrus.FieldLogger) {
	// This is a demo app with low QPS. trace.AlwaysSample() is used here
	// to make sure traces are available for observation and analysis.
	// In a production environment or high QPS setup please use
	// trace.ProbabilitySampler set at the desired probability.
	// TODO: Remove OpenCensus after full conversion to OpenTelemetry
	trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
	initOpenCensus(log)

	// Initialize exporter OTel Trace -> GCP Trace
	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
	exporter, err := texporter.NewExporter(texporter.WithProjectID(projectID))
	if err != nil {
		log.Fatalf("failed to initialize exporter: %v", err)
	}

	// Create trace provider with the exporter.
	tp, err := sdktrace.NewProvider(sdktrace.WithConfig(
		sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
		sdktrace.WithSyncer(exporter),
		// TODO: replace with predefined constant for GKE or autodetection when available
		sdktrace.WithResource(resource.New(standard.ServiceNameKey.String("GKE"))))
	if err != nil {
		log.Fatal("failed to initialize trace provider: %v", err)
	}
	global.SetTraceProvider(tp)
}

func initProfiling(log logrus.FieldLogger, service, version string) {
	// TODO(ahmetb) this method is duplicated in other microservices using Go
	// since they are not sharing packages.
	for i := 1; i <= 3; i++ {
		log = log.WithField("retry", i)
		if err := profiler.Start(profiler.Config{
			Service:        service,
			ServiceVersion: version,
			// ProjectID must be set if not running on GCP.
			// ProjectID: "my-project",
		}); err != nil {
			log.Warnf("warn: failed to start profiler: %+v", err)
		} else {
			log.Info("started stackdriver profiler")
			return
		}
		d := time.Second * 10 * time.Duration(i)
		log.Debugf("sleeping %v to retry initializing stackdriver profiler", d)
		time.Sleep(d)
	}
	log.Warn("warning: could not initialize stackdriver profiler after retrying, giving up")
}

func mustMapEnv(target *string, envKey string) {
	v := os.Getenv(envKey)
	if v == "" {
		panic(fmt.Sprintf("environment variable %q not set", envKey))
	}
	*target = v
}

func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr string) {
	var err error
	*conn, err = grpc.DialContext(ctx, addr,
		grpc.WithInsecure(),
		grpc.WithTimeout(time.Second*3),
		grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
		grpc.WithUnaryInterceptor(grpctrace.UnaryClientInterceptor(global.TraceProvider().Tracer("frontend"))),
		grpc.WithStreamInterceptor(grpctrace.StreamClientInterceptor(global.TraceProvider().Tracer("frontend"))))
	if err != nil {
		panic(errors.Wrapf(err, "grpc: failed to connect %s", addr))
	}
}
<commit_msg>restore ochttp metrics for userexp dashboard (#246)<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

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

	"cloud.google.com/go/profiler"
	"contrib.go.opencensus.io/exporter/stackdriver"
	"github.com/gorilla/mux"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"go.opencensus.io/plugin/ocgrpc"
	"go.opencensus.io/plugin/ochttp"
	"go.opencensus.io/plugin/ochttp/propagation/b3"
	"go.opencensus.io/stats/view"
	"go.opencensus.io/trace"

	// OTel Metric
	"go.opentelemetry.io/otel/api/metric"
	metricstdout "go.opentelemetry.io/otel/exporters/metric/stdout"
	"go.opentelemetry.io/otel/instrumentation/othttp"
	"go.opentelemetry.io/otel/sdk/metric/controller/push"

	// OTel Trace
	// OTel -> GCP Trace direct exporter for go
	texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
	"go.opentelemetry.io/otel/api/global"
	"go.opentelemetry.io/otel/api/standard"
	"go.opentelemetry.io/otel/instrumentation/grpctrace"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	"go.opentelemetry.io/otel/sdk/resource"

	"google.golang.org/grpc"
)

const (
	port            = "8080"
	defaultCurrency = "USD"
	cookieMaxAge    = 60 * 60 * 48

	cookiePrefix    = "shop_"
	cookieSessionID = cookiePrefix + "session-id"
	cookieCurrency  = cookiePrefix + "currency"
)

var (
	whitelistedCurrencies = map[string]bool{
		"USD": true,
		"EUR": true,
		"CAD": true,
		"JPY": true,
		"GBP": true,
		"TRY": true}
		// Custom Metrics for User Dashboard
		// TODO: use automatic metrics collection when Views API available in OpenTelemetry
		// TODO: remove these after automatically collected
		http_request_count metric.Int64Counter
		http_response_errors metric.Int64Counter
		http_request_latency metric.Int64ValueRecorder
)

type ctxKeySessionID struct{}

type frontendServer struct {
	productCatalogSvcAddr string
	productCatalogSvcConn *grpc.ClientConn

	currencySvcAddr string
	currencySvcConn *grpc.ClientConn

	cartSvcAddr string
	cartSvcConn *grpc.ClientConn

	recommendationSvcAddr string
	recommendationSvcConn *grpc.ClientConn

	checkoutSvcAddr string
	checkoutSvcConn *grpc.ClientConn

	shippingSvcAddr string
	shippingSvcConn *grpc.ClientConn

	adSvcAddr string
	adSvcConn *grpc.ClientConn
}

func main() {
	ctx := context.Background()
	log := logrus.New()
	log.Level = logrus.DebugLevel
	log.Formatter = &logrus.JSONFormatter{
		FieldMap: logrus.FieldMap{
			logrus.FieldKeyTime:  "timestamp",
			logrus.FieldKeyLevel: "severity",
			logrus.FieldKeyMsg:   "message",
		},
		TimestampFormat: time.RFC3339Nano,
	}
	log.Out = os.Stdout

	controller := initMetricsExporter(log)
	defer controller.Stop()

	go initProfiling(log, "frontend", "1.0.0")
	go initTelemetry(log)

	// TODO: register views when OpenTelemetry Views API is available
	meter := controller.Provider().Meter("hipstershop/frontend")
	// TODO: use automatic default metrics collection and remove custom metrics
	http_request_count = metric.Must(meter).NewInt64Counter("http_request_count")
	http_response_errors = metric.Must(meter).NewInt64Counter("http_response_errors")
	http_request_latency = metric.Must(meter).NewInt64ValueRecorder("http_request_latency")
	tracer := global.TraceProvider().Tracer("hipstershop/frontend")
	ctx, span := tracer.Start(ctx, "root")
	defer span.End()

	srvPort := port
	if os.Getenv("PORT") != "" {
		srvPort = os.Getenv("PORT")
	}
	addr := os.Getenv("LISTEN_ADDR")
	svc := new(frontendServer)
	mustMapEnv(&svc.productCatalogSvcAddr, "PRODUCT_CATALOG_SERVICE_ADDR")
	mustMapEnv(&svc.currencySvcAddr, "CURRENCY_SERVICE_ADDR")
	mustMapEnv(&svc.cartSvcAddr, "CART_SERVICE_ADDR")
	mustMapEnv(&svc.recommendationSvcAddr, "RECOMMENDATION_SERVICE_ADDR")
	mustMapEnv(&svc.checkoutSvcAddr, "CHECKOUT_SERVICE_ADDR")
	mustMapEnv(&svc.shippingSvcAddr, "SHIPPING_SERVICE_ADDR")
	mustMapEnv(&svc.adSvcAddr, "AD_SERVICE_ADDR")

	mustConnGRPC(ctx, &svc.currencySvcConn, svc.currencySvcAddr)
	mustConnGRPC(ctx, &svc.productCatalogSvcConn, svc.productCatalogSvcAddr)
	mustConnGRPC(ctx, &svc.cartSvcConn, svc.cartSvcAddr)
	mustConnGRPC(ctx, &svc.recommendationSvcConn, svc.recommendationSvcAddr)
	mustConnGRPC(ctx, &svc.shippingSvcConn, svc.shippingSvcAddr)
	mustConnGRPC(ctx, &svc.checkoutSvcConn, svc.checkoutSvcAddr)
	mustConnGRPC(ctx, &svc.adSvcConn, svc.adSvcAddr)

	r := mux.NewRouter()
	r.HandleFunc("/", svc.homeHandler).Methods(http.MethodGet, http.MethodHead)
	r.HandleFunc("/product/{id}", svc.productHandler).Methods(http.MethodGet, http.MethodHead)
	r.HandleFunc("/cart", svc.viewCartHandler).Methods(http.MethodGet, http.MethodHead)
	r.HandleFunc("/cart", svc.addToCartHandler).Methods(http.MethodPost)
	r.HandleFunc("/cart/empty", svc.emptyCartHandler).Methods(http.MethodPost)
	r.HandleFunc("/setCurrency", svc.setCurrencyHandler).Methods(http.MethodPost)
	r.HandleFunc("/logout", svc.logoutHandler).Methods(http.MethodGet)
	r.HandleFunc("/cart/checkout", svc.placeOrderHandler).Methods(http.MethodPost)
	r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))
	r.HandleFunc("/robots.txt", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "User-agent: *\nDisallow: /") })
	r.HandleFunc("/_healthz", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "ok") })

	var handler http.Handler = othttp.NewHandler(r, "frontend", // OpenTelemetry HTTP wrapper
		othttp.WithMessageEvents(othttp.ReadEvents, othttp.WriteEvents)) // Uses global meter and tracer
	handler = &logHandler{log: log, next: handler} // add logging
	handler = ensureSessionID(handler)             // add session ID
	handler = &ochttp.Handler{                     // add opencensus instrumentation
		Handler:     handler,
		Propagation: &b3.HTTPFormat{}}

	log.Infof("starting server on " + addr + ":" + srvPort)
	log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler))
}

// TODO: remove this after full conversion to OpenTelemetry
func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) {
	view.SetReportingPeriod(60 * time.Second)
	view.RegisterExporter(exporter)
	if err := view.Register(ochttp.DefaultServerViews...); err != nil {
		log.Warn("Error registering http default server views")
	} else {
		log.Info("Registered http default server views")
	}
	if err := view.Register(ocgrpc.DefaultClientViews...); err != nil {
		log.Warn("Error registering grpc default client views")
	} else {
		log.Info("Registered grpc default client views")
	}
}

// Initialize OpenTelemetry Metrics exporter
func initMetricsExporter(log logrus.FieldLogger) *push.Controller {
	// TODO: export to Cloud Monitoring instead of stdout
	pusher, err := metricstdout.InstallNewPipeline(metricstdout.Config{
		PrettyPrint: false,
	})
	if err != nil {
		log.Panicf("failed to initialize metric stdout exporter %v", err)
	}
	return pusher
}

// TODO: remove this after full conversion to OpenTelemetry
func initOpenCensus(log logrus.FieldLogger) {
	// TODO(ahmetb) this method is duplicated in other microservices using Go
	// since they are not sharing packages.
	for i := 1; i <= 3; i++ {
		log = log.WithField("retry", i)
		exporter, err := stackdriver.NewExporter(stackdriver.Options{})
		if err != nil {
			log.Warnf("failed to initialize stackdriver exporter: %+v", err)
		} else {
			trace.RegisterExporter(exporter)
			log.Info("registered stackdriver tracing")

			// Register the views to collect server stats.
			initStats(log, exporter)
			return
		}
		d := time.Second * 20 * time.Duration(i)
		log.Debugf("sleeping %v to retry initializing stackdriver exporter", d)
		time.Sleep(d)
	}
	log.Warn("could not initialize stackdriver exporter after retrying, giving up")
}

// Initialize Telemetry collection (Tracing, Metrics/Stats) with OpenCensus and OpenTelemetry
func initTelemetry(log logrus.FieldLogger) {
	// This is a demo app with low QPS. trace.AlwaysSample() is used here
	// to make sure traces are available for observation and analysis.
	// In a production environment or high QPS setup please use
	// trace.ProbabilitySampler set at the desired probability.
	// TODO: Remove OpenCensus after full conversion to OpenTelemetry
	trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
	initOpenCensus(log)

	// Initialize exporter OTel Trace -> GCP Trace
	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
	exporter, err := texporter.NewExporter(texporter.WithProjectID(projectID))
	if err != nil {
		log.Fatalf("failed to initialize exporter: %v", err)
	}

	// Create trace provider with the exporter.
	tp, err := sdktrace.NewProvider(sdktrace.WithConfig(
		sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
		sdktrace.WithSyncer(exporter),
		// TODO: replace with predefined constant for GKE or autodetection when available
		sdktrace.WithResource(resource.New(standard.ServiceNameKey.String("GKE"))))
	if err != nil {
		log.Fatal("failed to initialize trace provider: %v", err)
	}
	global.SetTraceProvider(tp)
}

func initProfiling(log logrus.FieldLogger, service, version string) {
	// TODO(ahmetb) this method is duplicated in other microservices using Go
	// since they are not sharing packages.
	for i := 1; i <= 3; i++ {
		log = log.WithField("retry", i)
		if err := profiler.Start(profiler.Config{
			Service:        service,
			ServiceVersion: version,
			// ProjectID must be set if not running on GCP.
			// ProjectID: "my-project",
		}); err != nil {
			log.Warnf("warn: failed to start profiler: %+v", err)
		} else {
			log.Info("started stackdriver profiler")
			return
		}
		d := time.Second * 10 * time.Duration(i)
		log.Debugf("sleeping %v to retry initializing stackdriver profiler", d)
		time.Sleep(d)
	}
	log.Warn("warning: could not initialize stackdriver profiler after retrying, giving up")
}

func mustMapEnv(target *string, envKey string) {
	v := os.Getenv(envKey)
	if v == "" {
		panic(fmt.Sprintf("environment variable %q not set", envKey))
	}
	*target = v
}

func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr string) {
	var err error
	*conn, err = grpc.DialContext(ctx, addr,
		grpc.WithInsecure(),
		grpc.WithTimeout(time.Second*3),
		grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
		grpc.WithUnaryInterceptor(grpctrace.UnaryClientInterceptor(global.TraceProvider().Tracer("frontend"))),
		grpc.WithStreamInterceptor(grpctrace.StreamClientInterceptor(global.TraceProvider().Tracer("frontend"))))
	if err != nil {
		panic(errors.Wrapf(err, "grpc: failed to connect %s", addr))
	}
}
<|endoftext|>


<commit_before>package wireup

import (
	"net/http"
	"time"

	international_autocomplete "github.com/smartystreets/smartystreets-go-sdk/international-autocomplete-api"
	international_street "github.com/smartystreets/smartystreets-go-sdk/international-street-api"
	"github.com/smartystreets/smartystreets-go-sdk/us-autocomplete-api"
	autocomplete_pro "github.com/smartystreets/smartystreets-go-sdk/us-autocomplete-pro-api"
	"github.com/smartystreets/smartystreets-go-sdk/us-extract-api"
	us_reverse_geo "github.com/smartystreets/smartystreets-go-sdk/us-reverse-geo-api"
	"github.com/smartystreets/smartystreets-go-sdk/us-street-api"
	"github.com/smartystreets/smartystreets-go-sdk/us-zipcode-api"
)

// BuildUSStreetAPIClient builds a client for the US Street API using the provided options.
func BuildUSStreetAPIClient(options ...Option) *street.Client {
	return configure(options...).buildUSStreetAPIClient()
}

// BuildUSZIPCodeAPIClient builds a client for the US ZIP Code API using the provided options.
func BuildUSZIPCodeAPIClient(options ...Option) *zipcode.Client {
	return configure(options...).buildUSZIPCodeAPIClient()
}

// BuildUSAutocompleteAPIClient builds a client for the US Autocomplete API using the provided options.
func BuildUSAutocompleteAPIClient(options ...Option) *autocomplete.Client {
	return configure(options...).buildUSAutocompleteAPIClient()
}

// BuildUSAutocompleteProAPIClient builds a client for the US Autocomplete API using the provided options.
func BuildUSAutocompleteProAPIClient(options ...Option) *autocomplete_pro.Client {
	return configure(options...).buildUSAutocompleteProAPIClient()
}

// BuildUSExtractAPIClient builds a client for the US Extract API using the provided options.
func BuildUSExtractAPIClient(options ...Option) *extract.Client {
	return configure(options...).buildUSExtractAPIClient()
}

// BuildInternationalStreetAPIClient builds a client for the International Street API using the provided options.
func BuildInternationalStreetAPIClient(options ...Option) *international_street.Client {
	return configure(options...).buildInternationalStreetAPIClient()
}

// BuildInternationalAutocompleteAPIClient builds a client for the International Autocomplete API using the provided options.
func BuildInternationalAutocompleteAPIClient(options ...Option) *international_autocomplete.Client {
	return configure(options...).buildInternationalAutocompleteAPIClient()
}

// BuildUSReverseGeocodingAPIClient builds a client for the US Reverse Geocoding API using the provided options.
func BuildUSReverseGeocodingAPIClient(options ...Option) *us_reverse_geo.Client {
	return configure(options...).buildUSReverseGeocodingAPIClient()
}

func configure(options ...Option) *clientBuilder {
	builder := newClientBuilder()
	for _, option := range options {
		if option != nil {
			option(builder)
		}
	}
	return builder
}

type Option func(builder *clientBuilder)

// SecretKeyCredential sets the authID and authToken for use with the client.
// In all but very few cases calling this method with a valid authID and authToken is required.
func SecretKeyCredential(authID, authToken string) Option {
	return func(builder *clientBuilder) {
		builder.withSecretKeyCredential(authID, authToken)
	}
}

// WebsiteKeyCredential sets the key and hostnameOrIP for use with the client.
// This kind of authentication is generally only used for client-side applications but it
// included here for completeness.
func WebsiteKeyCredential(key, hostnameOrIP string) Option {
	return func(builder *clientBuilder) {
		builder.withWebsiteKeyCredential(key, hostnameOrIP)
	}
}

// CustomBaseURL specifies the url that the client will use.
// In all but very few use cases the default value is sufficient and this method should not be called.
// The address provided will be consulted for scheme, host, and path values. Any other URL components
// such as the query string or fragment will be ignored.
func CustomBaseURL(address string) Option {
	return func(builder *clientBuilder) {
		builder.withCustomBaseURL(address)
	}
}

// MaxRetry specifies the number of times an API request will be resent in the
// case of network errors or unexpected results.
func MaxRetry(retries int) Option {
	return func(builder *clientBuilder) {
		builder.withMaxRetry(retries)
	}
}

// Timeout specifies the timeout for all API requests.
func Timeout(duration time.Duration) Option {
	return func(builder *clientBuilder) {
		builder.withTimeout(duration)
	}
}

// DebugHTTPOutput engages detailed HTTP request/response logging using functions from net/http/httputil.
func DebugHTTPOutput() Option {
	return func(builder *clientBuilder) {
		builder.withDebugHTTPOutput()
	}
}

// DebugHTTPTracing engages additional HTTP-level tracing for each API request.
func DebugHTTPTracing() Option {
	return func(builder *clientBuilder) {
		builder.withHTTPRequestTracing()
	}
}

// CustomHeader ensures the provided header is added to every API request made with the resulting client.
func CustomHeader(key, value string) Option {
	return func(builder *clientBuilder) {
		builder.withCustomHeader(key, value)
	}
}

// DisableKeepAlive disables keep-alive for API requests.
// This is helpful if your environment limits the number of open files.
func DisableKeepAlive() Option {
	return func(builder *clientBuilder) {
		builder.withoutKeepAlive()
	}
}

// ViaProxy saves the address of your proxy server through which to send all requests.
func ViaProxy(address string) Option {
	return func(builder *clientBuilder) {
		builder.viaProxy(address)
	}
}

// WithMaxIdleConnections sets MaxIdleConnsPerHost on the http.Transport used to send requests.
// Docs for http.Transport.MaxIdleConnsPerHost: https://golang.org/pkg/net/http/#Transport
// Also see: https://stackoverflow.com/questions/22881090/golang-about-maxidleconnsperhost-in-the-http-clients-transport
func WithMaxIdleConnections(max int) Option {
	return func(builder *clientBuilder) {
		builder.withMaxIdleConnections(max)
	}
}

// DisableHTTP2 prevents clients from making use of the http2 protocol. This is achieved by following the instructions
// from the http package documentation (see: https://golang.org/pkg/net/http):
// > "Programs that must disable HTTP/2 can do so by setting Transport.TLSNextProto to a non-nil, empty map."
func DisableHTTP2() Option {
	return func(builder *clientBuilder) {
		builder.disableHTTP2()
	}
}

// WithHTTPClient allows the caller to supply their own *http.Client. This is useful if you want full
// control over the http client and its properties, but keep in mind that it reduces the following
// options to no-ops (you would need to specify any of those details on the *http.Client you provide):
//
// - DisableHTTP2
// - WithMaxIdleConnections
// - ViaProxy
// - Timeout
//
func WithHTTPClient(client *http.Client) Option {
	return func(builder *clientBuilder) {
		builder.client = client
	}
}

// WithLicenses allows the caller to specify the subscription license (aka "track") they wish to use.
func WithLicenses(licenses ...string) Option {
	return func(builder *clientBuilder) {
		builder.licenses = append(builder.licenses, licenses...)
	}
}

// KeepTryingOnRateLimit will continue trying until the caller is within the bounds of their rate limit.
func KeepTryingOnRateLimit() Option {
	return func(builder *clientBuilder) {
		builder.withMaxRetry(999999)
	}
}
<commit_msg>API connection stays open when ignoring rate limit.<commit_after>package wireup

import (
	"net/http"
	"time"

	international_autocomplete "github.com/smartystreets/smartystreets-go-sdk/international-autocomplete-api"
	international_street "github.com/smartystreets/smartystreets-go-sdk/international-street-api"
	"github.com/smartystreets/smartystreets-go-sdk/us-autocomplete-api"
	autocomplete_pro "github.com/smartystreets/smartystreets-go-sdk/us-autocomplete-pro-api"
	"github.com/smartystreets/smartystreets-go-sdk/us-extract-api"
	us_reverse_geo "github.com/smartystreets/smartystreets-go-sdk/us-reverse-geo-api"
	"github.com/smartystreets/smartystreets-go-sdk/us-street-api"
	"github.com/smartystreets/smartystreets-go-sdk/us-zipcode-api"
)

// BuildUSStreetAPIClient builds a client for the US Street API using the provided options.
func BuildUSStreetAPIClient(options ...Option) *street.Client {
	return configure(options...).buildUSStreetAPIClient()
}

// BuildUSZIPCodeAPIClient builds a client for the US ZIP Code API using the provided options.
func BuildUSZIPCodeAPIClient(options ...Option) *zipcode.Client {
	return configure(options...).buildUSZIPCodeAPIClient()
}

// BuildUSAutocompleteAPIClient builds a client for the US Autocomplete API using the provided options.
func BuildUSAutocompleteAPIClient(options ...Option) *autocomplete.Client {
	return configure(options...).buildUSAutocompleteAPIClient()
}

// BuildUSAutocompleteProAPIClient builds a client for the US Autocomplete API using the provided options.
func BuildUSAutocompleteProAPIClient(options ...Option) *autocomplete_pro.Client {
	return configure(options...).buildUSAutocompleteProAPIClient()
}

// BuildUSExtractAPIClient builds a client for the US Extract API using the provided options.
func BuildUSExtractAPIClient(options ...Option) *extract.Client {
	return configure(options...).buildUSExtractAPIClient()
}

// BuildInternationalStreetAPIClient builds a client for the International Street API using the provided options.
func BuildInternationalStreetAPIClient(options ...Option) *international_street.Client {
	return configure(options...).buildInternationalStreetAPIClient()
}

// BuildInternationalAutocompleteAPIClient builds a client for the International Autocomplete API using the provided options.
func BuildInternationalAutocompleteAPIClient(options ...Option) *international_autocomplete.Client {
	return configure(options...).buildInternationalAutocompleteAPIClient()
}

// BuildUSReverseGeocodingAPIClient builds a client for the US Reverse Geocoding API using the provided options.
func BuildUSReverseGeocodingAPIClient(options ...Option) *us_reverse_geo.Client {
	return configure(options...).buildUSReverseGeocodingAPIClient()
}

func configure(options ...Option) *clientBuilder {
	builder := newClientBuilder()
	for _, option := range options {
		if option != nil {
			option(builder)
		}
	}
	return builder
}

type Option func(builder *clientBuilder)

// SecretKeyCredential sets the authID and authToken for use with the client.
// In all but very few cases calling this method with a valid authID and authToken is required.
func SecretKeyCredential(authID, authToken string) Option {
	return func(builder *clientBuilder) {
		builder.withSecretKeyCredential(authID, authToken)
	}
}

// WebsiteKeyCredential sets the key and hostnameOrIP for use with the client.
// This kind of authentication is generally only used for client-side applications but it
// included here for completeness.
func WebsiteKeyCredential(key, hostnameOrIP string) Option {
	return func(builder *clientBuilder) {
		builder.withWebsiteKeyCredential(key, hostnameOrIP)
	}
}

// CustomBaseURL specifies the url that the client will use.
// In all but very few use cases the default value is sufficient and this method should not be called.
// The address provided will be consulted for scheme, host, and path values. Any other URL components
// such as the query string or fragment will be ignored.
func CustomBaseURL(address string) Option {
	return func(builder *clientBuilder) {
		builder.withCustomBaseURL(address)
	}
}

// MaxRetry specifies the number of times an API request will be resent in the
// case of network errors or unexpected results.
func MaxRetry(retries int) Option {
	return func(builder *clientBuilder) {
		builder.withMaxRetry(retries)
	}
}

// Timeout specifies the timeout for all API requests.
func Timeout(duration time.Duration) Option {
	return func(builder *clientBuilder) {
		builder.withTimeout(duration)
	}
}

// DebugHTTPOutput engages detailed HTTP request/response logging using functions from net/http/httputil.
func DebugHTTPOutput() Option {
	return func(builder *clientBuilder) {
		builder.withDebugHTTPOutput()
	}
}

// DebugHTTPTracing engages additional HTTP-level tracing for each API request.
func DebugHTTPTracing() Option {
	return func(builder *clientBuilder) {
		builder.withHTTPRequestTracing()
	}
}

// CustomHeader ensures the provided header is added to every API request made with the resulting client.
func CustomHeader(key, value string) Option {
	return func(builder *clientBuilder) {
		builder.withCustomHeader(key, value)
	}
}

// DisableKeepAlive disables keep-alive for API requests.
// This is helpful if your environment limits the number of open files.
func DisableKeepAlive() Option {
	return func(builder *clientBuilder) {
		builder.withoutKeepAlive()
	}
}

// ViaProxy saves the address of your proxy server through which to send all requests.
func ViaProxy(address string) Option {
	return func(builder *clientBuilder) {
		builder.viaProxy(address)
	}
}

// WithMaxIdleConnections sets MaxIdleConnsPerHost on the http.Transport used to send requests.
// Docs for http.Transport.MaxIdleConnsPerHost: https://golang.org/pkg/net/http/#Transport
// Also see: https://stackoverflow.com/questions/22881090/golang-about-maxidleconnsperhost-in-the-http-clients-transport
func WithMaxIdleConnections(max int) Option {
	return func(builder *clientBuilder) {
		builder.withMaxIdleConnections(max)
	}
}

// DisableHTTP2 prevents clients from making use of the http2 protocol. This is achieved by following the instructions
// from the http package documentation (see: https://golang.org/pkg/net/http):
// > "Programs that must disable HTTP/2 can do so by setting Transport.TLSNextProto to a non-nil, empty map."
func DisableHTTP2() Option {
	return func(builder *clientBuilder) {
		builder.disableHTTP2()
	}
}

// WithHTTPClient allows the caller to supply their own *http.Client. This is useful if you want full
// control over the http client and its properties, but keep in mind that it reduces the following
// options to no-ops (you would need to specify any of those details on the *http.Client you provide):
//
// - DisableHTTP2
// - WithMaxIdleConnections
// - ViaProxy
// - Timeout
//
func WithHTTPClient(client *http.Client) Option {
	return func(builder *clientBuilder) {
		builder.client = client
	}
}

// WithLicenses allows the caller to specify the subscription license (aka "track") they wish to use.
func WithLicenses(licenses ...string) Option {
	return func(builder *clientBuilder) {
		builder.licenses = append(builder.licenses, licenses...)
	}
}

// KeepTryingOnRateLimit will continue trying until the caller is within the bounds of their rate limit.
func KeepTryingOnRateLimit() Option {
	return func(builder *clientBuilder) {
		builder.withMaxRetry(999999)
		builder.withTimeout(time.Second * 0)
	}
}
<|endoftext|>


<commit_before>/*
 * src/go/dnsresolvd.go
 * ============================================================================
 * DNS Resolver Daemon (dnsresolvd). Version 0.1
 * ============================================================================
 * A daemon that performs DNS lookups for the given hostname
 * passed in an HTTP request, with the focus on its implementation
 * using various programming languages. (net/http-boosted impl.)
 * ============================================================================
 * Copyright (C) 2017-2020 Radislav (Radicchio) Golubtsov
 *
 * (See the LICENSE file at the top of the source tree.)
 */

package main

import (
    "os"
    "strconv"
    "strings"
    "fmt"
    "log/syslog"
    "path/filepath"
    "net/http"
)

// The daemon entry point.
func main() {
    var ret int = _EXIT_SUCCESS

    var argc uint = uint(len(os.Args) - 1)

        daemon_name := os.Args[0]
    var port_number uint

    var print_banner_opt string = _EMPTY_STRING

    if (argc > 0) {
        port_number_, e := strconv.Atoi(os.Args[1])

        if (e == nil) { port_number = uint(port_number_) }

        if (argc > 1) {
            print_banner_opt = strings.ToUpper(os.Args[2])
        }
    } else {
        port_number = 0
    }

    if (print_banner_opt == _PRINT_BANNER_OPT) {
        _separator_draw(_DMN_DESCRIPTION)

        fmt.Printf(_DMN_NAME   + _COMMA_SPACE_SEP                             +
              _DMN_VERSION_S__ + _ONE_SPACE_STRING + _DMN_VERSION + _NEW_LINE +
              _DMN_DESCRIPTION +                                    _NEW_LINE +
              _DMN_COPYRIGHT__ + _ONE_SPACE_STRING + _DMN_AUTHOR  + _NEW_LINE)

        _separator_draw(_DMN_DESCRIPTION)
    }

    // Opening the system logger.
    log, _ := syslog.Dial(_EMPTY_STRING,   _EMPTY_STRING,
                          syslog.LOG_ERR | syslog.LOG_DAEMON,
                          filepath.Base(daemon_name))

    // Checking for args presence.
    if (argc == 0) {
        ret = _EXIT_FAILURE

        var argc_str string = strconv.Itoa(int(argc))

        fmt.Fprintf(os.Stderr, daemon_name      +
                    _ERR_MUST_BE_ONE_TWO_ARGS_1 + argc_str  +
                    _ERR_MUST_BE_ONE_TWO_ARGS_2 + _NEW_LINE + _NEW_LINE)

        log.Err(               daemon_name      +
                    _ERR_MUST_BE_ONE_TWO_ARGS_1 + argc_str  +
                    _ERR_MUST_BE_ONE_TWO_ARGS_2 + _NEW_LINE)

        fmt.Fprintf(os.Stderr, _MSG_USAGE_TEMPLATE_1 + daemon_name +
                               _MSG_USAGE_TEMPLATE_2 + _NEW_LINE   + _NEW_LINE)

        _cleanups_fixate(log)

        os.Exit(ret)
    }

    // Checking for port correctness.
    if ((port_number < _MIN_PORT) || (port_number > _MAX_PORT)) {
        ret = _EXIT_FAILURE

        fmt.Fprintf(os.Stderr, daemon_name         +
                    _ERR_PORT_MUST_BE_POSITIVE_INT + _NEW_LINE + _NEW_LINE)

        log.Err(               daemon_name         +
                    _ERR_PORT_MUST_BE_POSITIVE_INT + _NEW_LINE)

        fmt.Fprintf(os.Stderr, _MSG_USAGE_TEMPLATE_1 + daemon_name +
                               _MSG_USAGE_TEMPLATE_2 + _NEW_LINE   + _NEW_LINE)

        _cleanups_fixate(log)

        os.Exit(ret)
    }

    var port_number_str string = strconv.Itoa(int(port_number))

    fmt.Printf(_MSG_SERVER_STARTED_1 + port_number_str + _NEW_LINE +
               _MSG_SERVER_STARTED_2 +                   _NEW_LINE)

    log.Info(  _MSG_SERVER_STARTED_1 + port_number_str + _NEW_LINE +
               _MSG_SERVER_STARTED_2)

    // Defining the default request handler.
    _request_handler := func(resp http.ResponseWriter, req *http.Request) {
        var resp_buffer string = _EMPTY_STRING

        var hostname string = _DEF_HOSTNAME

        resp_buffer = "<!DOCTYPE html>"                                                   + _NEW_LINE +
""                                                       + _NEW_LINE +
""                                                                                + _NEW_LINE +
"<meta http-equiv=\"" + _HDR_CONTENT_TYPE_N      +                     "\"    content=\"" +
                        _HDR_CONTENT_TYPE_V_HTML +                     "\"           />"  + _NEW_LINE +
"<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"                            />"  + _NEW_LINE +
"<meta       name=\"viewport\"        content=\"width=device-width,initial-scale=1\" />"  + _NEW_LINE +
"<title>" + _DMN_NAME + "</title>"                                                        + _NEW_LINE +
""                                                                                + _NEW_LINE +
""                                                                                + _NEW_LINE +
"
"   +  hostname + _ONE_SPACE_STRING

        resp_buffer += req.Method

        resp_buffer += "
"  + _NEW_LINE +
                       "" + _NEW_LINE +
                       "" + _NEW_LINE

        fmt.Fprintf(resp, resp_buffer)
    }

    /*
     * Attaching HTTP request handlers to process incoming requests
     * and producing the response.
     */
    http.HandleFunc("/", _request_handler)

    // Starting up the HTTP listener on <port_number>.
    e := http.ListenAndServe(_COLON + port_number_str, nil)

    // Handling errors during start up of the listener.
    if (e != nil) {
        ret = _EXIT_FAILURE

        if (strings.Contains(e.Error(), _ERR_ADDR_ALREADY_IN_USE)) {
            fmt.Fprintf(os.Stderr, daemon_name   +
                        _ERR_CANNOT_START_SERVER +
                        _ERR_SRV_PORT_IS_IN_USE  + _NEW_LINE + _NEW_LINE)

            log.Err(               daemon_name   +
                        _ERR_CANNOT_START_SERVER +
                        _ERR_SRV_PORT_IS_IN_USE  + _NEW_LINE)
        } else {
            fmt.Fprintf(os.Stderr, daemon_name   +
                        _ERR_CANNOT_START_SERVER +
                        _ERR_SRV_UNKNOWN_REASON  + _NEW_LINE + _NEW_LINE)

            log.Err(               daemon_name   +
                        _ERR_CANNOT_START_SERVER +
                        _ERR_SRV_UNKNOWN_REASON  + _NEW_LINE)
        }

        _cleanups_fixate(log)

        os.Exit(ret)
    }

    // Making final cleanups.
    _cleanups_fixate(log)

    os.Exit(ret)
}

// vim:set nu et ts=4 sw=4:
<commit_msg>net/http/go: Start parsing and validating request params.<commit_after>/*
 * src/go/dnsresolvd.go
 * ============================================================================
 * DNS Resolver Daemon (dnsresolvd). Version 0.1
 * ============================================================================
 * A daemon that performs DNS lookups for the given hostname
 * passed in an HTTP request, with the focus on its implementation
 * using various programming languages. (net/http-boosted impl.)
 * ============================================================================
 * Copyright (C) 2017-2020 Radislav (Radicchio) Golubtsov
 *
 * (See the LICENSE file at the top of the source tree.)
 */

package main

import (
    "os"
    "strconv"
    "strings"
    "fmt"
    "log/syslog"
    "path/filepath"
    "net/http"
)

// The daemon entry point.
func main() {
    var ret int = _EXIT_SUCCESS

    var argc uint = uint(len(os.Args) - 1)

        daemon_name := os.Args[0]
    var port_number uint

    var print_banner_opt string = _EMPTY_STRING

    if (argc > 0) {
        port_number_, e := strconv.Atoi(os.Args[1])

        if (e == nil) { port_number = uint(port_number_) }

        if (argc > 1) {
            print_banner_opt = strings.ToUpper(os.Args[2])
        }
    } else {
        port_number = 0
    }

    if (print_banner_opt == _PRINT_BANNER_OPT) {
        _separator_draw(_DMN_DESCRIPTION)

        fmt.Printf(_DMN_NAME   + _COMMA_SPACE_SEP                             +
              _DMN_VERSION_S__ + _ONE_SPACE_STRING + _DMN_VERSION + _NEW_LINE +
              _DMN_DESCRIPTION +                                    _NEW_LINE +
              _DMN_COPYRIGHT__ + _ONE_SPACE_STRING + _DMN_AUTHOR  + _NEW_LINE)

        _separator_draw(_DMN_DESCRIPTION)
    }

    // Opening the system logger.
    log, _ := syslog.Dial(_EMPTY_STRING,   _EMPTY_STRING,
                          syslog.LOG_ERR | syslog.LOG_DAEMON,
                          filepath.Base(daemon_name))

    // Checking for args presence.
    if (argc == 0) {
        ret = _EXIT_FAILURE

        var argc_str string = strconv.Itoa(int(argc))

        fmt.Fprintf(os.Stderr, daemon_name      +
                    _ERR_MUST_BE_ONE_TWO_ARGS_1 + argc_str  +
                    _ERR_MUST_BE_ONE_TWO_ARGS_2 + _NEW_LINE + _NEW_LINE)

        log.Err(               daemon_name      +
                    _ERR_MUST_BE_ONE_TWO_ARGS_1 + argc_str  +
                    _ERR_MUST_BE_ONE_TWO_ARGS_2 + _NEW_LINE)

        fmt.Fprintf(os.Stderr, _MSG_USAGE_TEMPLATE_1 + daemon_name +
                               _MSG_USAGE_TEMPLATE_2 + _NEW_LINE   + _NEW_LINE)

        _cleanups_fixate(log)

        os.Exit(ret)
    }

    // Checking for port correctness.
    if ((port_number < _MIN_PORT) || (port_number > _MAX_PORT)) {
        ret = _EXIT_FAILURE

        fmt.Fprintf(os.Stderr, daemon_name         +
                    _ERR_PORT_MUST_BE_POSITIVE_INT + _NEW_LINE + _NEW_LINE)

        log.Err(               daemon_name         +
                    _ERR_PORT_MUST_BE_POSITIVE_INT + _NEW_LINE)

        fmt.Fprintf(os.Stderr, _MSG_USAGE_TEMPLATE_1 + daemon_name +
                               _MSG_USAGE_TEMPLATE_2 + _NEW_LINE   + _NEW_LINE)

        _cleanups_fixate(log)

        os.Exit(ret)
    }

    var port_number_str string = strconv.Itoa(int(port_number))

    fmt.Printf(_MSG_SERVER_STARTED_1 + port_number_str + _NEW_LINE +
               _MSG_SERVER_STARTED_2 +                   _NEW_LINE)

    log.Info(  _MSG_SERVER_STARTED_1 + port_number_str + _NEW_LINE +
               _MSG_SERVER_STARTED_2)

    // Defining the default request handler.
    _request_handler := func(resp http.ResponseWriter, req *http.Request) {
        var mtd string = req.Method

        var resp_buffer string = _EMPTY_STRING

        var hostname string = _DEF_HOSTNAME
        var frt      string = _PRM_FMT_JSON

        // --------------------------------------------------------------------
        // --- Parsing and validating request params - Begin ------------------
        // --------------------------------------------------------------------
               if (mtd == http.MethodGet ) {
            qry_ary := strings.Split(req.URL.RawQuery, _AMPER)

            fmt.Println(qry_ary)

            for i := 0; i < len(qry_ary); i++ {
                       if (strings.HasPrefix(     qry_ary[i], "h=")) {
                    hostname = strings.TrimPrefix(qry_ary[i], "h=")

                    fmt.Println(hostname)
                } else if (strings.HasPrefix(     qry_ary[i], "f=")) {
                    frt      = strings.TrimPrefix(qry_ary[i], "f=")

                    fmt.Println(frt)
                }
            }
        } else if (mtd == http.MethodPost) {
            fmt.Println(mtd)
        }
        // --------------------------------------------------------------------
        // --- Parsing and validating request params - End --------------------
        // --------------------------------------------------------------------

        resp_buffer = "<!DOCTYPE html>"                                                   + _NEW_LINE +
""                                                       + _NEW_LINE +
""                                                                                + _NEW_LINE +
"<meta http-equiv=\"" + _HDR_CONTENT_TYPE_N      +                     "\"    content=\"" +
                        _HDR_CONTENT_TYPE_V_HTML +                     "\"           />"  + _NEW_LINE +
"<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"                            />"  + _NEW_LINE +
"<meta       name=\"viewport\"        content=\"width=device-width,initial-scale=1\" />"  + _NEW_LINE +
"<title>" + _DMN_NAME + "</title>"                                                        + _NEW_LINE +
""                                                                                + _NEW_LINE +
""                                                                                + _NEW_LINE +
"
"   +  hostname + _ONE_SPACE_STRING

        resp_buffer += mtd

        resp_buffer += "
"  + _NEW_LINE +
                       "" + _NEW_LINE +
                       "" + _NEW_LINE

        fmt.Fprintf(resp, resp_buffer)
    }

    /*
     * Attaching HTTP request handlers to process incoming requests
     * and producing the response.
     */
    http.HandleFunc("/", _request_handler)

    // Starting up the HTTP listener on <port_number>.
    e := http.ListenAndServe(_COLON + port_number_str, nil)

    // Handling errors during start up of the listener.
    if (e != nil) {
        ret = _EXIT_FAILURE

        if (strings.Contains(e.Error(), _ERR_ADDR_ALREADY_IN_USE)) {
            fmt.Fprintf(os.Stderr, daemon_name   +
                        _ERR_CANNOT_START_SERVER +
                        _ERR_SRV_PORT_IS_IN_USE  + _NEW_LINE + _NEW_LINE)

            log.Err(               daemon_name   +
                        _ERR_CANNOT_START_SERVER +
                        _ERR_SRV_PORT_IS_IN_USE  + _NEW_LINE)
        } else {
            fmt.Fprintf(os.Stderr, daemon_name   +
                        _ERR_CANNOT_START_SERVER +
                        _ERR_SRV_UNKNOWN_REASON  + _NEW_LINE + _NEW_LINE)

            log.Err(               daemon_name   +
                        _ERR_CANNOT_START_SERVER +
                        _ERR_SRV_UNKNOWN_REASON  + _NEW_LINE)
        }

        _cleanups_fixate(log)

        os.Exit(ret)
    }

    // Making final cleanups.
    _cleanups_fixate(log)

    os.Exit(ret)
}

// vim:set nu et ts=4 sw=4:
<|endoftext|>


<commit_before>package crypto

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"errors"
	"hash"
	"strings"
)

const (
	DjangoSalt            = "django.core.signing.Signersigner"
	DjangoCookieSecPrefix = "django.http.cookies"
)

var (
	b64Pads = map[byte]string{
		0: "",
		1: "=",
		2: "==",
		3: "===",
	}
)

var (
	ErrBadSign = errors.New("签名不正确")
)

func SaltedHMAC(key_salt, value, secret []byte) hash.Hash {
	key := sha1.Sum(append(key_salt, secret...))
	hs := hmac.New(sha1.New, key[:])
	hs.Write(value)
	return hs
}

func b64_encode(bs []byte) string {
	s := base64.URLEncoding.EncodeToString(bs)
	return strings.TrimRight(s, "=")
}

func b64_decode(s string) ([]byte, error) {
	n := len(s) % 4
	pad := b64Pads[byte(n)]
	return base64.URLEncoding.DecodeString(s + pad)
}

func Base64HMAC(salt, value, secret string) string {
	hs := SaltedHMAC([]byte(salt), []byte(value), []byte(secret))
	return b64_encode(hs.Sum(nil))
}

func DjangoSign(value, sec string) string {
	return Base64HMAC(DjangoSalt, value, sec)
}

func DjangoSignCookie(cookieName, cookieValue, salt, sec string) string {
	salt = cookieName + salt + "signer"
	sec = DjangoCookieSecPrefix + sec
	return Base64HMAC(salt, cookieValue, sec)
}

func DjangoGetSignedCookie(cookieName, salt, sec, value string) (string, error) {
	parts := strings.Split(value, ":")
	var val, sig string
	if len(parts) == 2 { // no timestamp
		val, sig = parts[0], parts[1]
	} else if len(parts) == 3 {
		val = parts[0] + ":" + parts[1]
		sig = parts[2]
	} else {
		return "", ErrBadSign
	}

	if DjangoSignCookie(cookieName, val, salt, sec) != sig {
		return "", ErrBadSign
	}
	return strings.Split(val, ":")[0], nil
}
<commit_msg>DjangoGetSignedCookie returns val with timestamp<commit_after>package crypto

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"errors"
	"hash"
	"strings"
)

const (
	DjangoSalt            = "django.core.signing.Signersigner"
	DjangoCookieSecPrefix = "django.http.cookies"
)

var (
	b64Pads = map[byte]string{
		0: "",
		1: "=",
		2: "==",
		3: "===",
	}
)

var (
	ErrBadSign = errors.New("签名不正确")
)

func SaltedHMAC(key_salt, value, secret []byte) hash.Hash {
	key := sha1.Sum(append(key_salt, secret...))
	hs := hmac.New(sha1.New, key[:])
	hs.Write(value)
	return hs
}

func b64_encode(bs []byte) string {
	s := base64.URLEncoding.EncodeToString(bs)
	return strings.TrimRight(s, "=")
}

func b64_decode(s string) ([]byte, error) {
	n := len(s) % 4
	pad := b64Pads[byte(n)]
	return base64.URLEncoding.DecodeString(s + pad)
}

func Base64HMAC(salt, value, secret string) string {
	hs := SaltedHMAC([]byte(salt), []byte(value), []byte(secret))
	return b64_encode(hs.Sum(nil))
}

func DjangoSign(value, sec string) string {
	return Base64HMAC(DjangoSalt, value, sec)
}

func DjangoSignCookie(cookieName, cookieValue, salt, sec string) string {
	salt = cookieName + salt + "signer"
	sec = DjangoCookieSecPrefix + sec
	return Base64HMAC(salt, cookieValue, sec)
}

func DjangoGetSignedCookie(cookieName, salt, sec, value string) (string, error) {
	parts := strings.Split(value, ":")
	var val, sig string
	if len(parts) == 2 { // no timestamp
		val, sig = parts[0], parts[1]
	} else if len(parts) == 3 {
		val = parts[0] + ":" + parts[1]
		sig = parts[2]
	} else {
		return "", ErrBadSign
	}

	if DjangoSignCookie(cookieName, val, salt, sec) != sig {
		return "", ErrBadSign
	}
	return val, nil
}
<|endoftext|>


<commit_before>package aws

import (
	"net/http"
	"net/url"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/stelligent/mu/common"
)

// return a session.Options mutated with extra configuration values
func setupSessOptions(region string,
	proxy string,
	profile string) session.Options {
	sessOptions := session.Options{SharedConfigState: session.SharedConfigEnable}
	if region != common.Empty {
		sessOptions.Config.Region = aws.String(region)
	}
	if proxy != common.Empty {
		proxyHTTPClient := &http.Client{
			Transport: &http.Transport{
				Proxy: func(*http.Request) (*url.URL, error) {
					return url.Parse(proxy)
				},
			},
		}
		sessOptions.Config.HTTPClient = proxyHTTPClient
	}
	if profile != common.Empty {
		sessOptions.Profile = profile
	}
	return sessOptions
}

func initializeManagers(sess *session.Session, ctx *common.Context, dryrunPath string, skipVersionCheck bool) error {
	var err error
	// initialize StackManager
	ctx.StackManager, err = newStackManager(sess, ctx.ExtensionsManager, dryrunPath, skipVersionCheck)
	if err != nil {
		return err
	}

	// initialize ClusterManager
	ctx.ClusterManager, err = newClusterManager(sess)
	if err != nil {
		return err
	}

	// initialize InstanceManager
	ctx.InstanceManager, err = newInstanceManager(sess)
	if err != nil {
		return err
	}

	// initialize ElbManager
	ctx.ElbManager, err = newElbv2Manager(sess)
	if err != nil {
		return err
	}

	// initialize RdsManager
	ctx.RdsManager, err = newRdsManager(sess)
	if err != nil {
		return err
	}

	// initialize ParamManager
	ctx.ParamManager, err = newParamManager(sess)
	if err != nil {
		return err
	}

	// initialize CodePipelineManager
	ctx.PipelineManager, err = newPipelineManager(sess)
	if err != nil {
		return err
	}

	// initialize CloudWatchLogs
	ctx.LogsManager, err = newLogsManager(sess)
	if err != nil {
		return err
	}

	// initialize TaskManager
	ctx.TaskManager, err = newTaskManager(sess, &ctx.StackManager)
	if err != nil {
		return err
	}

	// initialize ArtifactManager
	ctx.ArtifactManager, err = newArtifactManager(sess)
	if err != nil {
		return err
	}

	// initialize SubscriptionManager
	ctx.SubscriptionManager, err = newSnsManager(sess)
	if err != nil {
		return err
	}

	// initialize the RolesetManager
	ctx.RolesetManager, err = newRolesetManager(ctx)
	if err != nil {
		return err
	}
	return nil
}

// InitializeContext loads manager objects
func InitializeContext(ctx *common.Context, profile string, assumeRole string, region string, dryrunPath string, skipVersionCheck bool, proxy string) error {

	sessOptions := setupSessOptions(region, proxy, profile)

	log.Debugf("Creating AWS session profile:%s region:%s proxy:%s", profile, region, proxy)
	sess, err := session.NewSessionWithOptions(sessOptions)
	if err != nil {
		return err
	}

	if assumeRole != common.Empty {
		// Create the credentials from AssumeRoleProvider to assume the role
		// referenced by the "myRoleARN" ARN.
		creds := stscreds.NewCredentials(sess, assumeRole)
		sess, err = session.NewSession(&aws.Config{Region: sess.Config.Region, HTTPClient: sess.Config.HTTPClient, Credentials: creds})
		if err != nil {
			return err
		}
	}
	err = initializeManagers(sess, ctx, dryrunPath, skipVersionCheck)
	if err != nil {
		return err
	}

	// initialize LocalCodePipelineManager
	localSess, err := session.NewSession()
	if err != nil {
		return err
	}
	ctx.LocalPipelineManager, _ = newPipelineManager(localSess)

	ctx.DockerOut = os.Stdout

	return nil
}
<commit_msg>Simplification<commit_after>package aws

import (
	"net/http"
	"net/url"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/stelligent/mu/common"
)

// return a session.Options mutated with extra configuration values
func setupSessOptions(region string,
	proxy string,
	profile string) session.Options {
	sessOptions := session.Options{SharedConfigState: session.SharedConfigEnable}
	if region != common.Empty {
		sessOptions.Config.Region = aws.String(region)
	}
	if proxy != common.Empty {
		proxyHTTPClient := &http.Client{
			Transport: &http.Transport{
				Proxy: func(*http.Request) (*url.URL, error) {
					return url.Parse(proxy)
				},
			},
		}
		sessOptions.Config.HTTPClient = proxyHTTPClient
	}
	if profile != common.Empty {
		sessOptions.Profile = profile
	}
	return sessOptions
}

func initializeManagers(sess *session.Session, ctx *common.Context, dryrunPath string, skipVersionCheck bool) error {
	var err error
	// initialize StackManager
	ctx.StackManager, err = newStackManager(sess, ctx.ExtensionsManager, dryrunPath, skipVersionCheck)
	if err != nil {
		return err
	}

	// initialize ClusterManager
	ctx.ClusterManager, err = newClusterManager(sess)
	if err != nil {
		return err
	}

	// initialize InstanceManager
	ctx.InstanceManager, err = newInstanceManager(sess)
	if err != nil {
		return err
	}

	// initialize ElbManager
	ctx.ElbManager, err = newElbv2Manager(sess)
	if err != nil {
		return err
	}

	// initialize RdsManager
	ctx.RdsManager, err = newRdsManager(sess)
	if err != nil {
		return err
	}

	// initialize ParamManager
	ctx.ParamManager, err = newParamManager(sess)
	if err != nil {
		return err
	}

	// initialize CodePipelineManager
	ctx.PipelineManager, err = newPipelineManager(sess)
	if err != nil {
		return err
	}

	// initialize CloudWatchLogs
	ctx.LogsManager, err = newLogsManager(sess)
	if err != nil {
		return err
	}

	// initialize TaskManager
	ctx.TaskManager, err = newTaskManager(sess, &ctx.StackManager)
	if err != nil {
		return err
	}

	// initialize ArtifactManager
	ctx.ArtifactManager, err = newArtifactManager(sess)
	if err != nil {
		return err
	}

	// initialize SubscriptionManager
	ctx.SubscriptionManager, err = newSnsManager(sess)
	if err != nil {
		return err
	}

	// initialize the RolesetManager
	ctx.RolesetManager, err = newRolesetManager(ctx)

	return err
}

// InitializeContext loads manager objects
func InitializeContext(ctx *common.Context, profile string, assumeRole string, region string, dryrunPath string, skipVersionCheck bool, proxy string) error {

	sessOptions := setupSessOptions(region, proxy, profile)

	log.Debugf("Creating AWS session profile:%s region:%s proxy:%s", profile, region, proxy)
	sess, err := session.NewSessionWithOptions(sessOptions)
	if err != nil {
		return err
	}

	if assumeRole != common.Empty {
		// Create the credentials from AssumeRoleProvider to assume the role
		// referenced by the "myRoleARN" ARN.
		creds := stscreds.NewCredentials(sess, assumeRole)
		sess, err = session.NewSession(&aws.Config{Region: sess.Config.Region, HTTPClient: sess.Config.HTTPClient, Credentials: creds})
		if err != nil {
			return err
		}
	}
	err = initializeManagers(sess, ctx, dryrunPath, skipVersionCheck)
	if err != nil {
		return err
	}

	// initialize LocalCodePipelineManager
	localSess, err := session.NewSession()
	if err != nil {
		return err
	}
	ctx.LocalPipelineManager, _ = newPipelineManager(localSess)

	ctx.DockerOut = os.Stdout

	return nil
}
<|endoftext|>