<commit_before>package cli

import (
	"fmt"
	"log"
	"time"

	"path/filepath"

	"github.com/bitrise-io/go-utils/command/git"
	flog "github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-utils/pathutil"
	"github.com/bitrise-io/go-utils/retry"
	"github.com/bitrise-io/stepman/models"
	"github.com/bitrise-io/stepman/stepman"
	"github.com/urfave/cli"
)

var stepInfoCommand = cli.Command{
	Name:  "step-info",
	Usage: "Prints the step definition (step.yml content).",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:   "library",
			Usage:  "Library of the step (options: LIBRARY_URI, git, path).",
			EnvVar: "STEPMAN_LIBRARY_URI",
		},
		cli.StringFlag{
			Name:  "id",
			Usage: "ID of the step (options: ID_IN_LIBRARY, GIT_URI, LOCAL_STEP_DIRECTORY_PATH).",
		},
		cli.StringFlag{
			Name:  "version",
			Usage: "Version of the step (options: VERSION_IN_LIBRARY, GIT_BRANCH_OR_TAG).",
		},
		cli.StringFlag{
			Name:  "format",
			Usage: "Output format (options: raw, json).",
		},
		cli.StringFlag{
			Name:   "collection, c",
			Usage:  "[DEPRECATED] Collection of step.",
			EnvVar: CollectionPathEnvKey,
		},
		cli.BoolFlag{
			Name:  "short",
			Usage: "[DEPRECATED] Show short version of infos.",
		},
		cli.StringFlag{
			Name:  "step-yml",
			Usage: "[DEPRECATED] Path of step.yml",
		},
	},
	Action: func(c *cli.Context) error {
		if err := stepInfo(c); err != nil {
			log.Fatalf("Command failed, error: %s", err)
		}
		return nil
	},
}

func stepInfo(c *cli.Context) error {
	// Input parsing
	library := c.String("library")
	if library == "" {
		collection := c.String(CollectionKey)
		library = collection
	}

	id := c.String(IDKey)
	if id == "" {
		stepYMLPath := c.String(StepYMLKey)
		if stepYMLPath != "" {
			id = stepYMLPath
			library = "path"
		}
	}

	if library == "" {
		return fmt.Errorf("Missing required input: library")
	}
	if id == "" {
		return fmt.Errorf("Missing required input: id")
	}

	version := c.String(VersionKey)

	format := c.String(FormatKey)
	if format == "" {
		format = OutputFormatRaw
	}
	if format != OutputFormatRaw && format != OutputFormatJSON {
		return fmt.Errorf("Invalid input value: format = %s", format)
	}

	var log flog.Logger
	log = flog.NewDefaultRawLogger()
	if format == OutputFormatJSON {
		log = flog.NewDefaultJSONLoger()
	}
	// ---

	stepInfo := models.StepInfoModel{
		Library: library,
		ID:      id,
		Version: version,
	}

	switch library {
	case "git":
		stepGitSourceURI := id
		tmpStepDir, err := pathutil.NormalizedOSTempDirPath("__step__")
		if err != nil {
			return fmt.Errorf("failed to create tmp dir, error: %s", err)
		}
		tagOrBranch := version
		if tagOrBranch == "" {
			tagOrBranch = "master"
		}

		if err := retry.Times(2).Wait(3 * time.Second).Try(func(attempt uint) error {
			return git.CloneTagOrBranchCommand(stepGitSourceURI, tmpStepDir, tagOrBranch).Run()
		}); err != nil {
			return fmt.Errorf("failed to clone step from: %s, error: %s", stepGitSourceURI, err)
		}

		stepDefinitionPth := filepath.Join(tmpStepDir, "step.yml")
		if exist, err := pathutil.IsPathExists(stepDefinitionPth); err != nil {
			return fmt.Errorf("failed to check if step definition (step.yml) exist at: %s, error: %s", stepDefinitionPth, err)
		} else if !exist {
			return fmt.Errorf("step definition (step.yml) does not exist at: %s", stepDefinitionPth)
		}

		step, err := stepman.ParseStepDefinition(stepDefinitionPth, false)
		if err != nil {
			return fmt.Errorf("failed to parse step definition at: %s, error: %s", stepDefinitionPth, err)
		}

		stepInfo.Version = tagOrBranch
		stepInfo.Step = step
		stepInfo.DefinitionPth = stepDefinitionPth
	case "path":
		stepDir := id
		stepDefinitionPth := filepath.Join(stepDir, "step.yml")
		if exist, err := pathutil.IsPathExists(stepDefinitionPth); err != nil {
			return fmt.Errorf("failed to check if step definition (step.yml) exist at: %s, error: %s", stepDefinitionPth, err)
		} else if !exist {
			return fmt.Errorf("step definition (step.yml) does not exist at: %s", stepDefinitionPth)
		}

		step, err := stepman.ParseStepDefinition(stepDefinitionPth, false)
		if err != nil {
			return fmt.Errorf("failed to parse step definition at: %s, error: %s", stepDefinitionPth, err)
		}

		stepInfo.Step = step
		stepInfo.DefinitionPth = stepDefinitionPth
	default: // library step
		// Check if setup was done for collection
		if exist, err := stepman.RootExistForLibrary(library); err != nil {
			return fmt.Errorf("Failed to check if setup was done for steplib (%s), error: %s", library, err)
		} else if !exist {
			if err := stepman.SetupLibrary(library); err != nil {
				return fmt.Errorf("Failed to setup steplib (%s), error: %s", library, err)
			}
		}

		stepVersion, err := stepman.ReadStepVersionInfo(library, id, version)
		if err != nil {
			return fmt.Errorf("Failed to read Step information, error: %s", err)
		}

		route, found := stepman.ReadRoute(library)
		if !found {
			return fmt.Errorf("No route found for library: %s", library)
		}

		stepDir := stepman.GetStepCollectionDirPath(route, id, stepVersion.Version)
		stepDefinitionPth := filepath.Join(stepDir, "step.yml")

		stepInfo.Step = stepVersion.Step
		stepInfo.Version = stepVersion.Version
		stepInfo.LatestVersion = stepVersion.LatestAvailableVersion
		stepInfo.DefinitionPth = stepDefinitionPth
	}

	log.Print(stepInfo)
	return nil
}
<commit_msg>do not force master if branch not specified (#230)<commit_after>package cli

import (
	"fmt"
	"log"
	"time"

	"path/filepath"

	"github.com/bitrise-io/go-utils/command/git"
	flog "github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-utils/pathutil"
	"github.com/bitrise-io/go-utils/retry"
	"github.com/bitrise-io/stepman/models"
	"github.com/bitrise-io/stepman/stepman"
	"github.com/urfave/cli"
)

var stepInfoCommand = cli.Command{
	Name:  "step-info",
	Usage: "Prints the step definition (step.yml content).",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:   "library",
			Usage:  "Library of the step (options: LIBRARY_URI, git, path).",
			EnvVar: "STEPMAN_LIBRARY_URI",
		},
		cli.StringFlag{
			Name:  "id",
			Usage: "ID of the step (options: ID_IN_LIBRARY, GIT_URI, LOCAL_STEP_DIRECTORY_PATH).",
		},
		cli.StringFlag{
			Name:  "version",
			Usage: "Version of the step (options: VERSION_IN_LIBRARY, GIT_BRANCH_OR_TAG).",
		},
		cli.StringFlag{
			Name:  "format",
			Usage: "Output format (options: raw, json).",
		},
		cli.StringFlag{
			Name:   "collection, c",
			Usage:  "[DEPRECATED] Collection of step.",
			EnvVar: CollectionPathEnvKey,
		},
		cli.BoolFlag{
			Name:  "short",
			Usage: "[DEPRECATED] Show short version of infos.",
		},
		cli.StringFlag{
			Name:  "step-yml",
			Usage: "[DEPRECATED] Path of step.yml",
		},
	},
	Action: func(c *cli.Context) error {
		if err := stepInfo(c); err != nil {
			log.Fatalf("Command failed, error: %s", err)
		}
		return nil
	},
}

func stepInfo(c *cli.Context) error {
	// Input parsing
	library := c.String("library")
	if library == "" {
		collection := c.String(CollectionKey)
		library = collection
	}

	id := c.String(IDKey)
	if id == "" {
		stepYMLPath := c.String(StepYMLKey)
		if stepYMLPath != "" {
			id = stepYMLPath
			library = "path"
		}
	}

	if library == "" {
		return fmt.Errorf("Missing required input: library")
	}
	if id == "" {
		return fmt.Errorf("Missing required input: id")
	}

	version := c.String(VersionKey)

	format := c.String(FormatKey)
	if format == "" {
		format = OutputFormatRaw
	}
	if format != OutputFormatRaw && format != OutputFormatJSON {
		return fmt.Errorf("Invalid input value: format = %s", format)
	}

	var log flog.Logger
	log = flog.NewDefaultRawLogger()
	if format == OutputFormatJSON {
		log = flog.NewDefaultJSONLoger()
	}
	// ---

	stepInfo := models.StepInfoModel{
		Library: library,
		ID:      id,
		Version: version,
	}

	switch library {
	case "git":
		stepGitSourceURI := id
		tmpStepDir, err := pathutil.NormalizedOSTempDirPath("__step__")
		if err != nil {
			return fmt.Errorf("failed to create tmp dir, error: %s", err)
		}
		tagOrBranch := version

		if err := retry.Times(2).Wait(3 * time.Second).Try(func(attempt uint) error {
			if tagOrBranch == "" {
				return git.CloneCommand(stepGitSourceURI, tmpStepDir).Run()
			}
			return git.CloneTagOrBranchCommand(stepGitSourceURI, tmpStepDir, tagOrBranch).Run()
		}); err != nil {
			return fmt.Errorf("failed to clone step from: %s, error: %s", stepGitSourceURI, err)
		}

		stepDefinitionPth := filepath.Join(tmpStepDir, "step.yml")
		if exist, err := pathutil.IsPathExists(stepDefinitionPth); err != nil {
			return fmt.Errorf("failed to check if step definition (step.yml) exist at: %s, error: %s", stepDefinitionPth, err)
		} else if !exist {
			return fmt.Errorf("step definition (step.yml) does not exist at: %s", stepDefinitionPth)
		}

		step, err := stepman.ParseStepDefinition(stepDefinitionPth, false)
		if err != nil {
			return fmt.Errorf("failed to parse step definition at: %s, error: %s", stepDefinitionPth, err)
		}

		stepInfo.Version = tagOrBranch
		stepInfo.Step = step
		stepInfo.DefinitionPth = stepDefinitionPth
	case "path":
		stepDir := id
		stepDefinitionPth := filepath.Join(stepDir, "step.yml")
		if exist, err := pathutil.IsPathExists(stepDefinitionPth); err != nil {
			return fmt.Errorf("failed to check if step definition (step.yml) exist at: %s, error: %s", stepDefinitionPth, err)
		} else if !exist {
			return fmt.Errorf("step definition (step.yml) does not exist at: %s", stepDefinitionPth)
		}

		step, err := stepman.ParseStepDefinition(stepDefinitionPth, false)
		if err != nil {
			return fmt.Errorf("failed to parse step definition at: %s, error: %s", stepDefinitionPth, err)
		}

		stepInfo.Step = step
		stepInfo.DefinitionPth = stepDefinitionPth
	default: // library step
		// Check if setup was done for collection
		if exist, err := stepman.RootExistForLibrary(library); err != nil {
			return fmt.Errorf("Failed to check if setup was done for steplib (%s), error: %s", library, err)
		} else if !exist {
			if err := stepman.SetupLibrary(library); err != nil {
				return fmt.Errorf("Failed to setup steplib (%s), error: %s", library, err)
			}
		}

		stepVersion, err := stepman.ReadStepVersionInfo(library, id, version)
		if err != nil {
			return fmt.Errorf("Failed to read Step information, error: %s", err)
		}

		route, found := stepman.ReadRoute(library)
		if !found {
			return fmt.Errorf("No route found for library: %s", library)
		}

		stepDir := stepman.GetStepCollectionDirPath(route, id, stepVersion.Version)
		stepDefinitionPth := filepath.Join(stepDir, "step.yml")

		stepInfo.Step = stepVersion.Step
		stepInfo.Version = stepVersion.Version
		stepInfo.LatestVersion = stepVersion.LatestAvailableVersion
		stepInfo.DefinitionPth = stepDefinitionPth
	}

	log.Print(stepInfo)
	return nil
}
<|endoftext|>


<commit_before>package irc

import (
	"errors"
	"log"
	"net"
)

func hasLocalAddr(inp string) (net.Addr, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return nil, err
	}

	for _, addr := range addrs {
		_, netw, err := net.ParseCIDR(addr.String())
		if err != nil {
			return nil, err
		}

		log.Println(netw.String())
		log.Println(netw.Network())

		if netw.Contains(net.ParseIP(inp)) {
			_, err := net.ResolveIPAddr("ip", inp)
			if err != nil {
				return nil, err
			}
			return &net.TCPAddr{
				IP: net.ParseIP(inp),
			}, nil
		}
	}

	return nil, errors.New("irc: Requested bindhost not found")
}
<commit_msg>remove this logging spew<commit_after>package irc

import (
	"errors"
	"net"
)

func hasLocalAddr(inp string) (net.Addr, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return nil, err
	}

	for _, addr := range addrs {
		_, netw, err := net.ParseCIDR(addr.String())
		if err != nil {
			return nil, err
		}

		if netw.Contains(net.ParseIP(inp)) {
			_, err := net.ResolveIPAddr("ip", inp)
			if err != nil {
				return nil, err
			}
			return &net.TCPAddr{
				IP: net.ParseIP(inp),
			}, nil
		}
	}

	return nil, errors.New("irc: Requested bindhost not found")
}
<|endoftext|>


<commit_before>package app

import (
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/golang/glog"
	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/leaderelection"
	"k8s.io/client-go/tools/leaderelection/resourcelock"
	"k8s.io/client-go/tools/record"

	"github.com/jetstack/cert-manager/cmd/controller/app/options"
	clientset "github.com/jetstack/cert-manager/pkg/client/clientset/versioned"
	intscheme "github.com/jetstack/cert-manager/pkg/client/clientset/versioned/scheme"
	informers "github.com/jetstack/cert-manager/pkg/client/informers/externalversions"
	"github.com/jetstack/cert-manager/pkg/controller"
	"github.com/jetstack/cert-manager/pkg/controller/clusterissuers"
	"github.com/jetstack/cert-manager/pkg/issuer"
	"github.com/jetstack/cert-manager/pkg/util/kube"
	kubeinformers "k8s.io/client-go/informers"
)

const (
	controllerAgentName = "cert-manager-controller"

	defaultNamespace = ""
)

func Run(opts *options.ControllerOptions, stopCh <-chan struct{}) {
	ctx, kubeCfg, err := buildControllerContext(opts)

	if err != nil {
		glog.Fatalf(err.Error())
	}

	run := func(_ <-chan struct{}) {
		var wg sync.WaitGroup
		var controllers = make(map[string]controller.Interface)
		for n, fn := range controller.Known() {
			if ctx.Namespace != "" && n == clusterissuers.ControllerName {
				glog.Infof("Skipping ClusterIssuer controller as cert-manager is scoped to a single namespace")
				continue
			}
			controllers[n] = fn(ctx)
		}
		for n, fn := range controllers {
			wg.Add(1)
			go func(n string, fn controller.Interface) {
				defer wg.Done()
				glog.V(4).Infof("Starting %s controller", n)

				err := fn(5, stopCh)

				if err != nil {
					glog.Fatalf("error running %s controller: %s", n, err.Error())
				}
			}(n, fn)
		}
		glog.V(4).Infof("Starting shared informer factory")
		ctx.SharedInformerFactory.Start(stopCh)
		ctx.KubeSharedInformerFactory.Start(stopCh)
		wg.Wait()
		glog.Fatalf("Control loops exited")
	}

	if !opts.LeaderElect {
		run(stopCh)
		return
	}

	leaderElectionClient, err := kubernetes.NewForConfig(rest.AddUserAgent(kubeCfg, "leader-election"))

	if err != nil {
		glog.Fatalf("error creating leader election client: %s", err.Error())
	}

	startLeaderElection(opts, leaderElectionClient, ctx.Recorder, run)
	panic("unreachable")
}

func buildControllerContext(opts *options.ControllerOptions) (*controller.Context, *rest.Config, error) {
	// Load the users Kubernetes config
	kubeCfg, err := kube.KubeConfig(opts.APIServerHost)

	if err != nil {
		return nil, nil, fmt.Errorf("error creating rest config: %s", err.Error())
	}

	// Create a Navigator api client
	intcl, err := clientset.NewForConfig(kubeCfg)

	if err != nil {
		return nil, nil, fmt.Errorf("error creating internal group client: %s", err.Error())
	}

	// Create a Kubernetes api client
	cl, err := kubernetes.NewForConfig(kubeCfg)

	if err != nil {
		return nil, nil, fmt.Errorf("error creating kubernetes client: %s", err.Error())
	}

	// Create event broadcaster
	// Add cert-manager types to the default Kubernetes Scheme so Events can be
	// logged properly
	intscheme.AddToScheme(scheme.Scheme)
	glog.V(4).Info("Creating event broadcaster")
	eventBroadcaster := record.NewBroadcaster()
	eventBroadcaster.StartLogging(glog.V(4).Infof)
	eventBroadcaster.StartRecordingToSink(&corev1.EventSinkImpl{Interface: cl.CoreV1().Events("")})
	recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: controllerAgentName})

	// We only create SharedInformerFactories for the --namespace specified to
	// watch. If this namespace is blank (i.e. the default, watch all
	// namespaces) then the factories will watch all namespaces.
	// If it is specified, all operations relating to ClusterIssuer resources
	// should be disabled and thus we don't need to also create factories for
	// the --cluster-resource-namespace.
	sharedInformerFactory := informers.NewFilteredSharedInformerFactory(intcl, time.Second*30, defaultNamespace, nil)
	kubeSharedInformerFactory := kubeinformers.NewFilteredSharedInformerFactory(cl, time.Second*30, defaultNamespace, nil)
	return &controller.Context{
		Client:                    cl,
		CMClient:                  intcl,
		Recorder:                  recorder,
		KubeSharedInformerFactory: kubeSharedInformerFactory,
		SharedInformerFactory:     sharedInformerFactory,
		IssuerFactory: issuer.NewFactory(&issuer.Context{
			Client:                          cl,
			CMClient:                        intcl,
			Recorder:                        recorder,
			KubeSharedInformerFactory:       kubeSharedInformerFactory,
			SharedInformerFactory:           sharedInformerFactory,
			Namespace:                       defaultNamespace,
			ClusterResourceNamespace:        opts.ClusterResourceNamespace,
			ACMEHTTP01SolverImage:           opts.ACMEHTTP01SolverImage,
			ClusterIssuerAmbientCredentials: opts.ClusterIssuerAmbientCredentials,
			IssuerAmbientCredentials:        opts.IssuerAmbientCredentials,
		}),
		Namespace:                defaultNamespace,
		ClusterResourceNamespace: opts.ClusterResourceNamespace,
	}, kubeCfg, nil
}

func startLeaderElection(opts *options.ControllerOptions, leaderElectionClient kubernetes.Interface, recorder record.EventRecorder, run func(<-chan struct{})) {
	// Identity used to distinguish between multiple controller manager instances
	id, err := os.Hostname()
	if err != nil {
		glog.Fatalf("error getting hostname: %s", err.Error())
	}

	// Lock required for leader election
	rl := resourcelock.ConfigMapLock{
		ConfigMapMeta: metav1.ObjectMeta{
			Namespace: opts.LeaderElectionNamespace,
			Name:      "cert-manager-controller",
		},
		Client: leaderElectionClient.CoreV1(),
		LockConfig: resourcelock.ResourceLockConfig{
			Identity:      id + "-external-cert-manager-controller",
			EventRecorder: recorder,
		},
	}

	// Try and become the leader and start controller manager loops
	leaderelection.RunOrDie(leaderelection.LeaderElectionConfig{
		Lock:          &rl,
		LeaseDuration: opts.LeaderElectionLeaseDuration,
		RenewDeadline: opts.LeaderElectionRenewDeadline,
		RetryPeriod:   opts.LeaderElectionRetryPeriod,
		Callbacks: leaderelection.LeaderCallbacks{
			OnStartedLeading: run,
			OnStoppedLeading: func() {
				glog.Fatalf("leaderelection lost")
			},
		},
	})
}
<commit_msg>controller: FilteredSharedInformer -> SharedInformer<commit_after>package app

import (
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/golang/glog"
	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/leaderelection"
	"k8s.io/client-go/tools/leaderelection/resourcelock"
	"k8s.io/client-go/tools/record"

	"github.com/jetstack/cert-manager/cmd/controller/app/options"
	clientset "github.com/jetstack/cert-manager/pkg/client/clientset/versioned"
	intscheme "github.com/jetstack/cert-manager/pkg/client/clientset/versioned/scheme"
	informers "github.com/jetstack/cert-manager/pkg/client/informers/externalversions"
	"github.com/jetstack/cert-manager/pkg/controller"
	"github.com/jetstack/cert-manager/pkg/controller/clusterissuers"
	"github.com/jetstack/cert-manager/pkg/issuer"
	"github.com/jetstack/cert-manager/pkg/util/kube"
	kubeinformers "k8s.io/client-go/informers"
)

const (
	controllerAgentName = "cert-manager-controller"

	defaultNamespace = ""
)

func Run(opts *options.ControllerOptions, stopCh <-chan struct{}) {
	ctx, kubeCfg, err := buildControllerContext(opts)

	if err != nil {
		glog.Fatalf(err.Error())
	}

	run := func(_ <-chan struct{}) {
		var wg sync.WaitGroup
		var controllers = make(map[string]controller.Interface)
		for n, fn := range controller.Known() {
			if ctx.Namespace != "" && n == clusterissuers.ControllerName {
				glog.Infof("Skipping ClusterIssuer controller as cert-manager is scoped to a single namespace")
				continue
			}
			controllers[n] = fn(ctx)
		}
		for n, fn := range controllers {
			wg.Add(1)
			go func(n string, fn controller.Interface) {
				defer wg.Done()
				glog.V(4).Infof("Starting %s controller", n)

				err := fn(5, stopCh)

				if err != nil {
					glog.Fatalf("error running %s controller: %s", n, err.Error())
				}
			}(n, fn)
		}
		glog.V(4).Infof("Starting shared informer factory")
		ctx.SharedInformerFactory.Start(stopCh)
		ctx.KubeSharedInformerFactory.Start(stopCh)
		wg.Wait()
		glog.Fatalf("Control loops exited")
	}

	if !opts.LeaderElect {
		run(stopCh)
		return
	}

	leaderElectionClient, err := kubernetes.NewForConfig(rest.AddUserAgent(kubeCfg, "leader-election"))

	if err != nil {
		glog.Fatalf("error creating leader election client: %s", err.Error())
	}

	startLeaderElection(opts, leaderElectionClient, ctx.Recorder, run)
	panic("unreachable")
}

func buildControllerContext(opts *options.ControllerOptions) (*controller.Context, *rest.Config, error) {
	// Load the users Kubernetes config
	kubeCfg, err := kube.KubeConfig(opts.APIServerHost)

	if err != nil {
		return nil, nil, fmt.Errorf("error creating rest config: %s", err.Error())
	}

	// Create a Navigator api client
	intcl, err := clientset.NewForConfig(kubeCfg)

	if err != nil {
		return nil, nil, fmt.Errorf("error creating internal group client: %s", err.Error())
	}

	// Create a Kubernetes api client
	cl, err := kubernetes.NewForConfig(kubeCfg)

	if err != nil {
		return nil, nil, fmt.Errorf("error creating kubernetes client: %s", err.Error())
	}

	// Create event broadcaster
	// Add cert-manager types to the default Kubernetes Scheme so Events can be
	// logged properly
	intscheme.AddToScheme(scheme.Scheme)
	glog.V(4).Info("Creating event broadcaster")
	eventBroadcaster := record.NewBroadcaster()
	eventBroadcaster.StartLogging(glog.V(4).Infof)
	eventBroadcaster.StartRecordingToSink(&corev1.EventSinkImpl{Interface: cl.CoreV1().Events("")})
	recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: controllerAgentName})

	// We only create SharedInformerFactories for the --namespace specified to
	// watch. If this namespace is blank (i.e. the default, watch all
	// namespaces) then the factories will watch all namespaces.
	// If it is specified, all operations relating to ClusterIssuer resources
	// should be disabled and thus we don't need to also create factories for
	// the --cluster-resource-namespace.
	sharedInformerFactory := informers.NewSharedInformerFactory(intcl, time.Second*30)
	kubeSharedInformerFactory := kubeinformers.NewSharedInformerFactory(cl, time.Second*30)
	return &controller.Context{
		Client:                    cl,
		CMClient:                  intcl,
		Recorder:                  recorder,
		KubeSharedInformerFactory: kubeSharedInformerFactory,
		SharedInformerFactory:     sharedInformerFactory,
		IssuerFactory: issuer.NewFactory(&issuer.Context{
			Client:                          cl,
			CMClient:                        intcl,
			Recorder:                        recorder,
			KubeSharedInformerFactory:       kubeSharedInformerFactory,
			SharedInformerFactory:           sharedInformerFactory,
			Namespace:                       defaultNamespace,
			ClusterResourceNamespace:        opts.ClusterResourceNamespace,
			ACMEHTTP01SolverImage:           opts.ACMEHTTP01SolverImage,
			ClusterIssuerAmbientCredentials: opts.ClusterIssuerAmbientCredentials,
			IssuerAmbientCredentials:        opts.IssuerAmbientCredentials,
		}),
		Namespace:                defaultNamespace,
		ClusterResourceNamespace: opts.ClusterResourceNamespace,
	}, kubeCfg, nil
}

func startLeaderElection(opts *options.ControllerOptions, leaderElectionClient kubernetes.Interface, recorder record.EventRecorder, run func(<-chan struct{})) {
	// Identity used to distinguish between multiple controller manager instances
	id, err := os.Hostname()
	if err != nil {
		glog.Fatalf("error getting hostname: %s", err.Error())
	}

	// Lock required for leader election
	rl := resourcelock.ConfigMapLock{
		ConfigMapMeta: metav1.ObjectMeta{
			Namespace: opts.LeaderElectionNamespace,
			Name:      "cert-manager-controller",
		},
		Client: leaderElectionClient.CoreV1(),
		LockConfig: resourcelock.ResourceLockConfig{
			Identity:      id + "-external-cert-manager-controller",
			EventRecorder: recorder,
		},
	}

	// Try and become the leader and start controller manager loops
	leaderelection.RunOrDie(leaderelection.LeaderElectionConfig{
		Lock:          &rl,
		LeaseDuration: opts.LeaderElectionLeaseDuration,
		RenewDeadline: opts.LeaderElectionRenewDeadline,
		RetryPeriod:   opts.LeaderElectionRetryPeriod,
		Callbacks: leaderelection.LeaderCallbacks{
			OnStartedLeading: run,
			OnStoppedLeading: func() {
				glog.Fatalf("leaderelection lost")
			},
		},
	})
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"time"

	"go.uber.org/zap"

	"github.com/miekg/dns"
	"github.com/shadowsocks/shadowsocks-go/encrypt"
	ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
)

const (
	logCntDelta int32 = 100
)

var (
	connCnt        int32
	nextLogConnCnt = logCntDelta
	// DNSClient give out the dns client for use
	DNSClient *dns.Client
	// DNSresolver give out the dns host to request
	DNSresolver func(host string) ([]string, error)
	enableDNS   bool
)

// handleConnection forward the request to the destination
func handleConnection(conn *ss.SecureConn, timeout int) {
	// first do the decode for ss protocol
	host, err := ss.GetRequest(conn)
	if err != nil {
		ss.Logger.Error("ss server get request failed", zap.Stringer("src", conn.RemoteAddr()), zap.Error(err))
		return
	}
	ss.Logger.Info("ss server accept the ss request", zap.Stringer("src", conn.RemoteAddr()), zap.String("dst", host))

	atomic.AddInt32(&connCnt, 1)
	defer atomic.AddInt32(&connCnt, -1)
	if atomic.LoadInt32(&connCnt)-nextLogConnCnt >= 0 {
		ss.Logger.Warn("Number of client connections reaches", zap.Int32("count", nextLogConnCnt))
		nextLogConnCnt += logCntDelta
	}

	// do dns resolve
	if enableDNS {
		hostname := strings.Split(host, ":")
		answers, err := DNSresolver(hostname[0])
		if err != nil {
			ss.Logger.Error("error in resolve dns, resolver returned error", zap.Error(err))
		} else if len(hostname) != 2 || len(answers) == 0 {
			ss.Logger.Error("error in resolve dns, request illegal")
		} else {
			ss.Logger.Info("dns look up get response", zap.String("host", hostname[0]), zap.Strings("A record", answers))
			// use the first hostname to request by default
			for _, v := range answers {
				if v != "" {
					host = net.JoinHostPort(v, hostname[1])
					break
				}
			}
		}
	}

	// request the remote
	ss.Logger.Debug("connecting to the request host", zap.String("host", host))
	remote, err := net.Dial("tcp", host)
	if err != nil {
		if ne, ok := err.(*net.OpError); ok && (ne.Err == syscall.EMFILE || ne.Err == syscall.ENFILE) {
			// log too many open file error
			// EMFILE is process reaches open file limits, ENFILE is system limit
			ss.Logger.Error("dial error:", zap.Error(err))
		} else {
			ss.Logger.Error("error connecting to host:", zap.String("host", host), zap.Error(err))
		}
		return
	}

	remote.(*net.TCPConn).SetKeepAlive(true)

	ss.Logger.Debug("piping remote to host:", zap.Stringer("remote", conn.RemoteAddr()), zap.String("host", host))

	defer conn.Close()
	defer remote.Close()
	// NOTICE: timeout should be setted carefully to avoid cutting the correct tcp stream
	if timeout > 0 {
		ss.Logger.Info("connection timeout setted", zap.Int("timeout", timeout))
		conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
		remote.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
	}

	// close the server at the right time
	wg := sync.WaitGroup{}
	wg.Add(1)
	go ss.PipeThenClose(conn, remote.(*net.TCPConn), wg.Done)
	ss.PipeThenClose(remote.(*net.TCPConn), conn, func() {})
	wg.Wait()

	return
}

func waitSignal() {
	var sigChan = make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
	for {
		s := <-sigChan
		switch s {
		case syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
			ss.Logger.Info("Caught signal , shuting down", zap.Stringer("signal", s))
			os.Exit(0)
		default:
			ss.Logger.Error("Caught meaning lease signal", zap.Stringer("signal", s))
		}
	}
}

// serveTCP accept incoming request and handle
func serveTCP(ln *ss.Listener, timeout int) {
	defer ln.Close()
	for {
		// accept should not be blocked, so here just return a ss warped connection
		sconn, err := ln.Accept()
		if err != nil {
			ss.Logger.Error("error in ss server accept connection", zap.Error(err))
			continue
		}
		go handleConnection(sconn, timeout)
	}
}

// start the ss remote servers listen on given ports
func run(conf *ss.Config) {
	for addr, pass := range conf.PortPassword {
		cipher, err := encrypt.NewCipher(conf.Method, pass)
		if err != nil {
			ss.Logger.Fatal("Failed create cipher", zap.Error(err))
		}
		// listen on :addr ,so makesure you have the enough priority to do this
		ln, err := ss.Listen("tcp", net.JoinHostPort("", addr), cipher.Copy(), conf.Timeout)
		if err != nil {
			ss.Logger.Fatal("error listening port", zap.String("port", addr), zap.Error(err))
		}
		ss.Logger.Info("server listening port", zap.String("port", addr))
		go serveTCP(ln, conf.Timeout)
	}
}

// serveUDP read from the udp listen and forward the request
// only do the forward here, the backward doing in another sequence
func serveUDP(servein *ss.SecurePacketConn) {
	defer servein.Close()
	buf := make([]byte, 4096)
	for {
		n, srcAddr, err := servein.ReadFrom(buf)
		if err != nil {
			ss.Logger.Error("[udp]read from server packet listen error", zap.Error(err))
			// TODO should this be continue?
			// warning may better
			continue
		}
		// TODO handle the connection : when to close the conn
		// for loop is right?

		go ss.ForwardUDPConn(servein, srcAddr, buf[:n])
	}
}

// strat a server for each port & password
func runUDP(conf *ss.Config) {
	addrPadd := conf.PortPassword
	for addr, pass := range addrPadd {
		ss.Logger.Info("[UDP] listening udp", zap.String("port", addr))
		cipher, err := encrypt.NewCipher(conf.Method, pass)
		if err != nil {
			ss.Logger.Error("[UDP] failed create cipher", zap.Error(err))
			os.Exit(1)
		}
		SecurePacketConn, err := ss.ListenPacket("udp", ":"+addr, cipher, conf.Timeout)
		if err != nil {
			ss.Logger.Error("[UDP] error listening packetconn", zap.String("address", addr), zap.Error(err))
			os.Exit(1)
		}
		go serveUDP(SecurePacketConn)
	}
}

func checkConfig(config *ss.Config) error {
	//server -- server port should match
	//port -- port password should patch
	if config.Password == "" && config.PortPassword == nil {
		return errors.New("missing passwd for config")
	}
	if len(config.GetServerPortArray()) != len(config.GetPasswordArray()) {
		return errors.New("server port array and password array mismatching")
	}

	if config.DNSServer != "" {
		enableDNS = true
		ss.Logger.Info("setting the dns server", zap.String("dns", config.DNSServer))
		initializeDNSResolver(config.DNSServer)
	}
	return nil
}

func main() {
	var err error
	var udp, printVer bool
	var Timeout, core, matrixport int
	var ServerPort, configFile, Password, Method, DNSServer string

	var config *ss.Config

	flag.BoolVar(&printVer, "v", false, "print version")
	flag.StringVar(&configFile, "config", "", "specify config file")
	flag.StringVar(&Password, "passwd", "", "password")
	flag.StringVar(&ServerPort, "port", "", "server port")
	flag.IntVar(&Timeout, "timeout", 300, "timeout in seconds")
	flag.StringVar(&Method, "method", "aes-256-cfb", "encryption method, default: aes-256-cfb")
	flag.IntVar(&core, "core", 0, "maximum number of CPU cores to use, default is determinied by Go runtime")
	flag.IntVar(&matrixport, "pprof", 0, "set the metrix port to Enable the pprof and matrix(TODO), keep it 0 will disable this feature")
	flag.StringVar(&ss.Level, "level", "info", "given the logger level for ss to logout info, can be set in debug info warn error")
	flag.BoolVar(&udp, "enable_udp", false, "diasbale UDP service, enable by default")
	flag.StringVar(&DNSServer, "dns", "", "set the dns server for server, default will use the system dns server in /etc/resolv.conf")
	flag.Parse()
	if !flag.Parsed() {
		flag.Usage()
		os.Exit(0)
	}
	if printVer {
		ss.PrintVersion()
		os.Exit(0)
	}

	// init the logger
	ss.SetLogger()
	ss.Logger.Info("Starting shadowsocks remote server")

	// set the pprof
	if matrixport > 0 {
		go http.ListenAndServe(":"+strconv.Itoa(matrixport), nil)
	}

	// set the options for the config new
	var opts []ss.ConfOption

	// choose the encrypt method then check
	if Method == "" {
		Method = "aes-256-cfb"
		opts = append(opts, ss.WithEncryptMethod("aes-256-cfb"))
	}
	if err = encrypt.CheckCipherMethod(Method); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	opts = append(opts, ss.WithEncryptMethod(Method))

	// set the dns server
	if DNSServer != "" {
		opts = append(opts, ss.WithDNSServer(DNSServer))
	}

	// check the passwd if not set
	if Password != "" {
		opts = append(opts, ss.WithPassword(Password))
		if ServerPort != "" {
			opts = append(opts, ss.WithServerPort(ServerPort))
			opts = append(opts, ss.WithPortPassword(ServerPort, Password))
		}
	}

	config = ss.NewConfig(opts...)

	// parse the config from the config file
	if configFile != "" {
		ss.Logger.Info("ss server loading config file", zap.String("path", configFile))
		config, err = ss.ParseConfig(configFile)
		if err != nil {
			ss.Logger.Fatal("error in reading the ss config file", zap.String("path", configFile), zap.Error(err))
		}
	}
	ss.Logger.Debug("show the ss config", zap.Stringer("config", config))

	// check the config
	if err = checkConfig(config); err != nil {
		ss.Logger.Error("error in chack config", zap.Error(err))
		os.Exit(1)
	}

	// if core is defined ,then set the max proecssor
	if core > 0 {
		runtime.GOMAXPROCS(core)
	}

	// start the shadowsocks server
	go run(config)
	if udp { //enable udp if diable_udp not set
		go runUDP(config)
	}

	// wait for the ctrl-c signal
	waitSignal()
}

func initializeDNSResolver(server string) {
	if server == "" {
		ss.Logger.Fatal("error in set dns resolver, server is nil")
		return
	}

	c := dns.Client{}
	m := dns.Msg{}

	DNSresolver = func(host string) ([]string, error) {
		ansers := make([]string, 1, 4)

		m.SetQuestion(host+".", dns.TypeA)
		r, t, err := c.Exchange(&m, server+":53")
		if err != nil {
			return nil, err
		}
		ss.Logger.Debug("DNS lookup domain cost", zap.Stringer("time", t))
		if len(r.Answer) == 0 {
			return nil, errors.New("No results returned")
		}
		for _, ans := range r.Answer {
			if ans.Header().Rrtype == dns.TypeA {
				ansers = append(ansers, ans.(*dns.A).A.String())
			}
		}
		return ansers, nil
	}
}
<commit_msg>fixing the server<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"time"

	"go.uber.org/zap"

	"github.com/miekg/dns"
	"github.com/shadowsocks/shadowsocks-go/encrypt"
	ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
)

const (
	logCntDelta int32 = 100
)

var (
	connCnt        int32
	nextLogConnCnt = logCntDelta
	// DNSClient give out the dns client for use
	DNSClient *dns.Client
	// DNSresolver give out the dns host to request
	DNSresolver func(host string) ([]string, error)
	enableDNS   bool
)

// handleConnection forward the request to the destination
func handleConnection(conn net.Conn, timeout int) {
	// first do the decode for ss protocol
	host, err := ss.GetRequest(conn)
	if err != nil {
		ss.Logger.Error("ss server get request failed", zap.Stringer("src", conn.RemoteAddr()), zap.Error(err))
		return
	}
	ss.Logger.Info("ss server accept the ss request", zap.Stringer("src", conn.RemoteAddr()), zap.String("dst", host))

	atomic.AddInt32(&connCnt, 1)
	defer atomic.AddInt32(&connCnt, -1)
	if atomic.LoadInt32(&connCnt)-nextLogConnCnt >= 0 {
		ss.Logger.Warn("Number of client connections reaches", zap.Int32("count", nextLogConnCnt))
		nextLogConnCnt += logCntDelta
	}

	// do dns resolve
	if enableDNS {
		hostname := strings.Split(host, ":")
		answers, err := DNSresolver(hostname[0])
		if err != nil {
			ss.Logger.Error("error in resolve dns, resolver returned error", zap.Error(err))
		} else if len(hostname) != 2 || len(answers) == 0 {
			ss.Logger.Error("error in resolve dns, request illegal")
		} else {
			ss.Logger.Info("dns look up get response", zap.String("host", hostname[0]), zap.Strings("A record", answers))
			// use the first hostname to request by default
			for _, v := range answers {
				if v != "" {
					host = net.JoinHostPort(v, hostname[1])
					break
				}
			}
		}
	}

	// request the remote
	ss.Logger.Debug("connecting to the request host", zap.String("host", host))
	remote, err := net.Dial("tcp", host)
	if err != nil {
		if ne, ok := err.(*net.OpError); ok && (ne.Err == syscall.EMFILE || ne.Err == syscall.ENFILE) {
			// log too many open file error
			// EMFILE is process reaches open file limits, ENFILE is system limit
			ss.Logger.Error("dial error:", zap.Error(err))
		} else {
			ss.Logger.Error("error connecting to host:", zap.String("host", host), zap.Error(err))
		}
		return
	}
	tcpremote, ok := remote.(*net.TCPConn)
	if !ok {
		//TODO
		return
	}

	tcpremote.SetKeepAlive(true)

	ss.Logger.Debug("piping remote to host:", zap.Stringer("remote", conn.RemoteAddr()), zap.String("host", host))

	defer conn.Close()
	defer remote.Close()
	// NOTICE: timeout should be setted carefully to avoid cutting the correct tcp stream
	if timeout > 0 {
		ss.Logger.Info("connection timeout setted", zap.Int("timeout", timeout))
		conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
		remote.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
	}

	// close the server at the right time
	wg := sync.WaitGroup{}
	wg.Add(1)
	go ss.PipeThenClose(conn.(*net.TCPConn), tcpremote, wg.Done)
	ss.PipeThenClose(tcpremote, conn.(*net.TCPConn), func() {})
	wg.Wait()

	return
}

func waitSignal() {
	var sigChan = make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
	for {
		s := <-sigChan
		switch s {
		case syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
			ss.Logger.Info("Caught signal , shuting down", zap.Stringer("signal", s))
			os.Exit(0)
		default:
			ss.Logger.Error("Caught meaning lease signal", zap.Stringer("signal", s))
		}
	}
}

// serveTCP accept incoming request and handle
func serveTCP(ln net.Listener, timeout int) {
	defer ln.Close()
	for {
		// accept should not be blocked, so here just return a ss warped connection
		sconn, err := ln.Accept()
		if err != nil {
			ss.Logger.Error("error in ss server accept connection", zap.Error(err))
			continue
		}
		go handleConnection(sconn, timeout)
	}
}

// start the ss remote servers listen on given ports
func run(conf *ss.Config) {
	for addr, pass := range conf.PortPassword {
		cipher, err := encrypt.PickCipher(conf.Method, pass)
		if err != nil {
			ss.Logger.Fatal("Failed create cipher", zap.Error(err))
		}
		// listen on :addr ,so makesure you have the enough priority to do this
		ln, err := ss.SecureListen("tcp", net.JoinHostPort("", addr), cipher.Copy(), conf.Timeout)
		if err != nil {
			ss.Logger.Fatal("error listening port", zap.String("port", addr), zap.Error(err))
		}
		ss.Logger.Info("server listening port", zap.String("port", addr))
		go serveTCP(ln, conf.Timeout)
	}
}

// serveUDP read from the udp listen and forward the request
// only do the forward here, the backward doing in another sequence
func serveUDP(servein net.PacketConn) {
	defer servein.Close()
	buf := make([]byte, 4096)
	for {
		n, srcAddr, err := servein.ReadFrom(buf)
		if err != nil {
			ss.Logger.Error("[udp]read from server packet listen error", zap.Error(err))
			// TODO should this be continue?
			// warning may better
			continue
		}
		// TODO handle the connection : when to close the conn
		// for loop is right?
		go ss.ForwardUDPConn(servein, srcAddr, buf[:n])
	}
}

// strat a server for each port & password
func runUDP(conf *ss.Config) {
	addrPadd := conf.PortPassword
	for addr, pass := range addrPadd {
		ss.Logger.Info("[UDP] listening udp", zap.String("port", addr))
		cipher, err := encrypt.PickCipher(conf.Method, pass)
		if err != nil {
			ss.Logger.Error("[UDP] failed create cipher", zap.Error(err))
			os.Exit(1)
		}
		SecurePacketConn, err := ss.SecureListenPacket("udp", ":"+addr, cipher, conf.Timeout)
		if err != nil {
			ss.Logger.Error("[UDP] error listening packetconn", zap.String("address", addr), zap.Error(err))
			os.Exit(1)
		}
		go serveUDP(SecurePacketConn)
	}
}

func checkConfig(config *ss.Config) error {
	//server -- server port should match
	//port -- port password should patch
	if config.Password == "" && config.PortPassword == nil {
		return errors.New("missing passwd for config")
	}
	if len(config.GetServerPortArray()) != len(config.GetPasswordArray()) {
		return errors.New("server port array and password array mismatching")
	}

	if config.DNSServer != "" {
		enableDNS = true
		ss.Logger.Info("setting the dns server", zap.String("dns", config.DNSServer))
		initializeDNSResolver(config.DNSServer)
	}
	return nil
}

func main() {
	var err error
	var udp, printVer bool
	var Timeout, core, matrixport int
	var ServerPort, configFile, Password, Method, DNSServer string

	var config *ss.Config

	flag.BoolVar(&printVer, "v", false, "print version")
	flag.StringVar(&configFile, "config", "", "specify config file")
	flag.StringVar(&Password, "passwd", "", "password")
	flag.StringVar(&ServerPort, "port", "", "server port")
	flag.IntVar(&Timeout, "timeout", 300, "timeout in seconds")
	flag.StringVar(&Method, "method", "aes-256-cfb", "encryption method, default: aes-256-cfb")
	flag.IntVar(&core, "core", 0, "maximum number of CPU cores to use, default is determinied by Go runtime")
	flag.IntVar(&matrixport, "pprof", 0, "set the metrix port to Enable the pprof and matrix(TODO), keep it 0 will disable this feature")
	flag.StringVar(&ss.Level, "level", "info", "given the logger level for ss to logout info, can be set in debug info warn error")
	flag.BoolVar(&udp, "enable_udp", false, "diasbale UDP service, enable by default")
	flag.StringVar(&DNSServer, "dns", "", "set the dns server for server, default will use the system dns server in /etc/resolv.conf")
	flag.Parse()
	if !flag.Parsed() {
		flag.Usage()
		os.Exit(0)
	}
	if printVer {
		ss.PrintVersion()
		os.Exit(0)
	}

	// init the logger
	ss.SetLogger()
	ss.Logger.Info("Starting shadowsocks remote server")

	// set the pprof
	if matrixport > 0 {
		go http.ListenAndServe(":"+strconv.Itoa(matrixport), nil)
	}

	// set the options for the config new
	var opts []ss.ConfOption

	// choose the encrypt method then check
	if Method == "" {
		Method = "aes-256-cfb"
		opts = append(opts, ss.WithEncryptMethod("aes-256-cfb"))
	}
	if err = encrypt.CheckCipherMethod(Method); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	opts = append(opts, ss.WithEncryptMethod(Method))

	// set the dns server
	if DNSServer != "" {
		opts = append(opts, ss.WithDNSServer(DNSServer))
	}

	// check the passwd if not set
	if Password != "" {
		opts = append(opts, ss.WithPassword(Password))
		if ServerPort != "" {
			opts = append(opts, ss.WithServerPort(ServerPort))
			opts = append(opts, ss.WithPortPassword(ServerPort, Password))
		}
	}

	config = ss.NewConfig(opts...)

	// parse the config from the config file
	if configFile != "" {
		ss.Logger.Info("ss server loading config file", zap.String("path", configFile))
		config, err = ss.ParseConfig(configFile)
		if err != nil {
			ss.Logger.Fatal("error in reading the ss config file", zap.String("path", configFile), zap.Error(err))
		}
	}
	ss.Logger.Debug("show the ss config", zap.Stringer("config", config))

	// check the config
	if err = checkConfig(config); err != nil {
		ss.Logger.Error("error in chack config", zap.Error(err))
		os.Exit(1)
	}

	// if core is defined ,then set the max proecssor
	if core > 0 {
		runtime.GOMAXPROCS(core)
	}

	// start the shadowsocks server
	go run(config)
	if udp { //enable udp if diable_udp not set
		go runUDP(config)
	}

	// wait for the ctrl-c signal
	waitSignal()
}

func initializeDNSResolver(server string) {
	if server == "" {
		ss.Logger.Fatal("error in set dns resolver, server is nil")
		return
	}

	c := dns.Client{}
	m := dns.Msg{}

	DNSresolver = func(host string) ([]string, error) {
		ansers := make([]string, 1, 4)

		m.SetQuestion(host+".", dns.TypeA)
		r, t, err := c.Exchange(&m, server+":53")
		if err != nil {
			return nil, err
		}
		ss.Logger.Debug("DNS lookup domain cost", zap.Stringer("time", t))
		if len(r.Answer) == 0 {
			return nil, errors.New("No results returned")
		}
		for _, ans := range r.Answer {
			if ans.Header().Rrtype == dns.TypeA {
				ansers = append(ansers, ans.(*dns.A).A.String())
			}
		}
		return ansers, nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"path/filepath"
	"strings"
	"text/template"
	"time"

	// third-party
	"github.com/gorilla/websocket"
	"github.com/stephen-soltesz/go/collection"
)

func startViewServer(host string, port int) {
	go hub.run()
	addr := fmt.Sprintf("%s:%d", host, port)
	http.HandleFunc("/", serveHome)
	http.HandleFunc("/ws", serveWs)
	debugLogger.Printf("HTTP: listen on: %s\n", addr)
	err := http.ListenAndServe(addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

// hub maintains the set of active connections and broadcasts messages to the
// connections.
type hubset struct {
	// Registered connections.
	connections map[*connection]bool

	// Inbound messages from the connections.
	broadcast chan []byte

	// Register requests from the connections.
	register chan *connection

	// Unregister requests from connections.
	unregister chan *connection
}

var hub = hubset{
	broadcast:   make(chan []byte),
	register:    make(chan *connection),
	unregister:  make(chan *connection),
	connections: make(map[*connection]bool),
}

func (h *hubset) run() {
	for {
		select {
		case c := <-hub.register:
			hub.connections[c] = true
		case c := <-hub.unregister:
			delete(hub.connections, c)
			close(c.send)
		case m := <-hub.broadcast:
			for c := range hub.connections {
				select {
				case c.send <- m:
				default:
					close(c.send)
					delete(hub.connections, c)
				}
			}
		}
	}
}

const (
	// Time allowed to write a message to the peer.
	writeWait = 10 * time.Second

	// Time allowed to read the next pong message from the peer.
	pongWait = 60 * time.Second

	// Send pings to peer with this period. Must be less than pongWait.
	pingPeriod = (pongWait * 9) / 10

	// Maximum message size allowed from peer.
	maxMessageSize = 512

	// directory of local resources
	localPrefix = "resources"
)

// connection is an middleman between the websocket connection and the hub.
type connection struct {
	// The websocket connection.
	ws *websocket.Conn

	// Buffered channel of outbound messages.
	send chan []byte
}

// readPump pumps messages from the websocket connection to the hub.
func (c *connection) readPump() {
	defer func() {
		hub.unregister <- c
		c.ws.Close()
	}()
	c.ws.SetReadLimit(maxMessageSize)
	c.ws.SetReadDeadline(time.Now().Add(pongWait))
	c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
	for {
		_, message, err := c.ws.ReadMessage()
		if err != nil {
			break
		}
		hub.broadcast <- message
	}
}

// write writes a message with the given message type and payload.
func (c *connection) write(mt int, payload []byte) error {
	c.ws.SetWriteDeadline(time.Now().Add(writeWait))
	return c.ws.WriteMessage(mt, payload)
}

func pngToUri(data []byte) []byte {
	var uridata bytes.Buffer

	encoded := base64.StdEncoding.EncodeToString(data)
	//data:image/svg+xml;charset=utf-8;base64,
	//uridata.WriteString("data:image/png;base64,")
	uridata.WriteString("data:image/svg+xml;charset=utf-8;base64,")
	uridata.WriteString(encoded)

	return uridata.Bytes()
}

func getPngUri() []byte {
	var pngimg bytes.Buffer
	collector := collection.Default()
	if err := collector.Plot(&pngimg, *plotWidth, *plotHeight, *timestamp); err != nil {
		return nil
	}
	if *debug {
		// save the current image to a file.
		fmt.Println("writing debug.svg")
		ioutil.WriteFile("debug.svg", pngimg.Bytes(), 0644)
	}
	return pngToUri(pngimg.Bytes())
}

func (c *connection) genMessages() {
	count := 0
	for {
		count += 1
		msg := getPngUri()
		if msg == nil {
			panic(errors.New("failed to convert png"))
		}
		c.write(websocket.TextMessage, msg)
		time.Sleep(time.Second)
	}
}

// writePump pumps messages from the hub to the websocket connection.
func (c *connection) writePump() {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
		c.ws.Close()
	}()
	for {
		select {
		case message, ok := <-c.send:
			if !ok {
				c.write(websocket.CloseMessage, []byte{})
				return
			}
			if err := c.write(websocket.TextMessage, message); err != nil {
				return
			}
		case <-ticker.C:
			if err := c.write(websocket.PingMessage, []byte{}); err != nil {
				return
			}
		}
	}
}

// serverWs handles webocket requests from the peer.
func serveWs(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	if r.Header.Get("Origin") != "http://"+r.Host {
		http.Error(w, "Origin not allowed", 403)
		return
	}
	debugLogger.Printf("ws:GET %s\n", r.Host)
	ws, err := websocket.Upgrade(w, r, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		debugLogger.Printf("ws:Error %s %s\n", r.Host, err)
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		debugLogger.Printf("ws:Error %s %s\n", r.Host, err)
		return
	}
	c := &connection{send: make(chan []byte, 256), ws: ws}
	hub.register <- c
	debugLogger.Printf("ws:Starting read/write pumps %s\n", r.Host)
	go c.writePump()
	// send canvas size as first message.
	msgStr := fmt.Sprintf("%d,%d\n", *plotWidth, *plotHeight)
	c.write(websocket.TextMessage, []byte(msgStr))
	go c.genMessages()
	c.readPump()
}

func splitAll(path string) (string, string, string) {
	dir, file := filepath.Split(path)
	if file == "" {
		file = "home.html"
	}
	ext := strings.Trim(filepath.Ext(file), ".")
	return dir, file, ext
}

func serveHome(w http.ResponseWriter, r *http.Request) {
	var data []byte
	var err error

	if r.Method != "GET" {
		http.Error(w, "Method nod allowed", 405)
		return
	}
	_, file, ext := splitAll(r.URL.Path)

	resourcefile := fmt.Sprintf("%s/%s", localPrefix, file)
	if *debug {
		data, err = ioutil.ReadFile(resourcefile)
	} else {
		data, err = Asset(resourcefile)
	}

	if err != nil {
		debugLogger.Printf("Error: requested: %s\n", r.URL.Path)
		http.Error(w, "Not found", 404)
		return
	}

	tmpl := template.Must(template.New(resourcefile).Parse(string(data)))
	if ext == "html" {
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
	} else if ext == "js" {
		w.Header().Set("Content-Type", "text/javascript; charset=utf-8")
	} else if ext == "css" {
		w.Header().Set("Content-Type", "text/css; charset=utf-8")
	}
	tmpl.Execute(w, r.Host)
}
<commit_msg>serve svg and config urls, disable websocket / hub.<commit_after>package main

import (
	"bytes"
//  "encoding/base64"
  "encoding/json"
//  "errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"path/filepath"
	"strconv"
	"strings"
	"text/template"
	"time"

	// third-party
	"github.com/gorilla/websocket"
	"github.com/stephen-soltesz/go/collection"
)

func startViewServer(host string, port int) {
//	go hub.run()
	addr := fmt.Sprintf("%s:%d", host, port)
	http.HandleFunc("/", serveHome)
	http.HandleFunc("/ws", serveWs)
	http.HandleFunc("/svg", serveSvg)
	http.HandleFunc("/config", serveConfig)
	debugLogger.Printf("HTTP: listen on: %s\n", addr)
	err := http.ListenAndServe(addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

// hub maintains the set of active connections and broadcasts messages to the
// connections.
/*
type hubset struct {
	// Registered connections.
	connections map[*connection]bool

	// Inbound messages from the connections.
	broadcast chan []byte

	// Register requests from the connections.
	register chan *connection

	// Unregister requests from connections.
	unregister chan *connection
}

var hub = hubset{
	broadcast:   make(chan []byte),
	register:    make(chan *connection),
	unregister:  make(chan *connection),
	connections: make(map[*connection]bool),
}

func (h *hubset) run() {
	for {
		select {
		case c := <-hub.register:
			hub.connections[c] = true
		case c := <-hub.unregister:
			delete(hub.connections, c)
			close(c.send)
		case m := <-hub.broadcast:
			for c := range hub.connections {
				select {
				case c.send <- m:
				default:
					close(c.send)
					delete(hub.connections, c)
				}
			}
		}
	}
}
*/

const (
	// Time allowed to write a message to the peer.
	writeWait = 10 * time.Second

	// Time allowed to read the next pong message from the peer.
	pongWait = 60 * time.Second

	// Send pings to peer with this period. Must be less than pongWait.
	pingPeriod = (pongWait * 9) / 10

	// Maximum message size allowed from peer.
	maxMessageSize = 512

	// directory of local resources
	localPrefix = "resources"
)

// connection is an middleman between the websocket connection and the hub.
type connection struct {
	// The websocket connection.
	ws *websocket.Conn

	// Buffered channel of outbound messages.
	send chan []byte
}

// readPump pumps messages from the websocket connection to the hub.
/*
func (c *connection) readPump() {
	defer func() {
		hub.unregister <- c
		c.ws.Close()
	}()
	c.ws.SetReadLimit(maxMessageSize)
	c.ws.SetReadDeadline(time.Now().Add(pongWait))
	c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
	for {
		_, message, err := c.ws.ReadMessage()
		if err != nil {
			break
		}
		hub.broadcast <- message
	}
}
*/

// write writes a message with the given message type and payload.
func (c *connection) write(mt int, payload []byte) error {
	c.ws.SetWriteDeadline(time.Now().Add(writeWait))
	return c.ws.WriteMessage(mt, payload)
}

func getSvg(delta int64) []byte {
	var img bytes.Buffer
	collector := collection.Default()
	if err := collector.Plot(&img, *plotWidth, *plotHeight, float64(delta)); err != nil {
		return nil
	}
	return img.Bytes()
}

type Config struct {
	Success bool `json:"success"`
	Width   int	 `json:"width"`
	Height  int  `json:"height"`
}

func serveConfig(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	cfg := &Config{Success: true, Width: *plotWidth, Height: *plotHeight}
	msg, err := json.Marshal(cfg)
	if err != nil {
		http.Error(w, "Server Error", 500)
		return
	}
	w.Write(msg)
	return
}

/*
func pngToUri(data []byte) []byte {
	var uridata bytes.Buffer

	encoded := base64.StdEncoding.EncodeToString(data)
	//data:image/svg+xml;charset=utf-8;base64,
	//uridata.WriteString("data:image/png;base64,")
	uridata.WriteString("data:image/svg+xml;charset=utf-8;base64,")
	uridata.WriteString(encoded)

	return uridata.Bytes()
}

func getPngUri() []byte {
	var pngimg bytes.Buffer
	collector := collection.Default()
	if err := collector.Plot(&pngimg, *plotWidth, *plotHeight, 0); err != nil {
		return nil
	}
	return pngToUri(pngimg.Bytes())
}

func (c *connection) genMessages() {
	count := 0
	for {
		count += 1
		msg := getPngUri()
		if msg == nil {
			panic(errors.New("failed to convert png"))
		}
		c.write(websocket.TextMessage, msg)
		time.Sleep(time.Second)
	}
}
*/

// writePump pumps messages from the hub to the websocket connection.
/*
func (c *connection) writePump() {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
		c.ws.Close()
	}()
	for {
		select {
		case message, ok := <-c.send:
			if !ok {
				c.write(websocket.CloseMessage, []byte{})
				return
			}
			if err := c.write(websocket.TextMessage, message); err != nil {
				return
			}
		case <-ticker.C:
			if err := c.write(websocket.PingMessage, []byte{}); err != nil {
				return
			}
		}
	}
}
*/

// serverWs handles webocket requests from the peer.
func serveWs(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	if r.Header.Get("Origin") != "http://"+r.Host {
		http.Error(w, "Origin not allowed", 403)
		return
	}
	debugLogger.Printf("ws:GET %s\n", r.Host)
	ws, err := websocket.Upgrade(w, r, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		debugLogger.Printf("ws:Error %s %s\n", r.Host, err)
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		debugLogger.Printf("ws:Error %s %s\n", r.Host, err)
		return
	}
	c := &connection{send: make(chan []byte, 256), ws: ws}
	//hub.register <- c
	debugLogger.Printf("ws:Starting read/write pumps %s\n", r.Host)
	//go c.writePump()
	// send canvas size as first message.
	msgStr := fmt.Sprintf("%d,%d\n", *plotWidth, *plotHeight)
	c.write(websocket.TextMessage, []byte(msgStr))
	//go c.genMessages()
	//c.readPump()
}

func splitAll(path string) (string, string, string) {
	dir, file := filepath.Split(path)
	if file == "" {
		file = "home.html"
	}
	ext := strings.Trim(filepath.Ext(file), ".")
	return dir, file, ext
}

func serveHome(w http.ResponseWriter, r *http.Request) {
	var data []byte
	var err error

	if r.Method != "GET" {
		http.Error(w, "Method nod allowed", 405)
		return
	}
	_, file, ext := splitAll(r.URL.Path)

	resourcefile := fmt.Sprintf("%s/%s", localPrefix, file)
	if *debug {
		data, err = ioutil.ReadFile(resourcefile)
	} else {
		data, err = Asset(resourcefile)
	}

	if err != nil {
		debugLogger.Printf("Error: requested: %s\n", r.URL.Path)
		http.Error(w, "Not found", 404)
		return
	}

	tmpl := template.Must(template.New(resourcefile).Parse(string(data)))
	if ext == "html" {
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
	} else if ext == "js" {
		w.Header().Set("Content-Type", "text/javascript; charset=utf-8")
	} else if ext == "css" {
		w.Header().Set("Content-Type", "text/css; charset=utf-8")
	}
	tmpl.Execute(w, r.Host)
}

func serveSvg(w http.ResponseWriter, r *http.Request) {
	var err error
	var delta int64

	if r.Method != "GET" {
		http.Error(w, "Method nod allowed", 405)
		return
	}
	formVals, err := url.ParseQuery(r.URL.RawQuery)
	if err != nil {
		http.Error(w, "Bad Request", 400)
		return
	}

	deltaStr, ok := formVals["delta"]
	if !ok {
		http.Error(w, "Bad Request. All parameters not provided.", 400)
		return
	}

	if len(deltaStr) > 0 {
		delta, err = strconv.ParseInt(deltaStr[0], 10, 64)
		if err != nil {
			http.Error(w, "Bad Request. Could not convert parameters.", 400)
			return
		}
	} else {
		delta = 0
	}

	svg := getSvg(delta)
	if svg != nil {
		if *debug {
			// save the current image to a file.
			fmt.Println("writing debug.svg")
			ioutil.WriteFile("debug.svg", svg, 0644)
		}
		w.Header().Set("Content-Type", "image/svg+xml; charset=utf-8")
		w.Write(svg)
	}
}
<|endoftext|>


<commit_before>package client

import (
	"errors"
	"fmt"
	"time"

	"strconv"

	"sourcegraph.com/sourcegraph/api_router"
	"sourcegraph.com/sourcegraph/srcgraph/db_common"
	"sourcegraph.com/sourcegraph/srcgraph/repo"
	"sourcegraph.com/sourcegraph/srcgraph/task2"
)

// BuildsService communicates with the build-related endpoints in the
// Sourcegraph API.
type BuildsService interface {
	// Get fetches a build.
	Get(build BuildSpec, opt *BuildGetOptions) (*Build, Response, error)

	// List builds.
	List(opt *BuildListOptions) ([]*Build, Response, error)

	// ListByRepository lists builds for a repository.
	ListByRepository(repo RepositorySpec, opt *BuildListByRepositoryOptions) ([]*Build, Response, error)

	// Create a new build. The build will run asynchronously (Create does not
	// wait for it to return. To monitor the build's status, use Get.)
	Create(repo RepositorySpec, conf BuildConfig) (*Build, Response, error)

	// ListBuildTasks lists the tasks associated with a build.
	ListBuildTasks(build BuildSpec, opt *BuildTaskListOptions) ([]*BuildTask, Response, error)
}

type buildsService struct {
	client *Client
}

var _ BuildsService = &buildsService{}

type BuildSpec struct {
	BID int64
}

func (s *BuildSpec) RouteVars() map[string]string {
	return map[string]string{"BID": fmt.Sprintf("%d", s.BID)}
}

// A Build represents a scheduled, completed, or failed repository analysis and
// import job.
type Build struct {
	BID       int64
	Repo      repo.RID
	CommitID  string             `db:"commit_id"`
	CreatedAt time.Time          `db:"created_at"`
	StartedAt db_common.NullTime `db:"started_at"`
	EndedAt   db_common.NullTime `db:"ended_at"`
	Success   bool
	Failure   bool

	BuildConfig

	// RepoURI is populated (as a convenience) in results by Get and List but
	// should not be set when creating builds (it will be ignored).
	RepoURI repo.URI `db:"repo_uri" json:",omitempty"`
}

// IDString returns a succinct string that uniquely identifies this build.
func (b *Build) IDString() string { return buildIDString(b.BID) }

func buildIDString(bid int64) string { return "B" + strconv.FormatInt(bid, 36) }

// A BuildTask represents an individual step of a build.
type BuildTask struct {
	TID int64

	// BID is the build that this task is a part of.
	BID int64

	UnitType string
	Unit     string

	Title string

	StartedAt db_common.NullTime `db:"started_at"`
	EndedAt   db_common.NullTime `db:"ended_at"`

	Success bool
	Failure bool
}

// IDString returns a succinct string that uniquely identifies this build task.
func (t *BuildTask) IDString() string {
	return buildIDString(t.BID) + "-T" + strconv.FormatInt(t.TID, 36)
}

// LogURL is the URL to the logs for this task.
func (t *BuildTask) LogURL() string {
	return task2.LogURLForTag(t.IDString())
}

// BuildConfig configures a repository build.
type BuildConfig struct {
	// Import is whether to import the build data into the database when the
	// build is complete. The data must be imported for Sourcegraph's web app or
	// API to use it, except that unimported build data is available through the
	// BuildData service. (TODO(sqs): BuildData isn't yet implemented.)
	Import bool

	// Queue is whether this build should be enqueued. If enqueued, any worker
	// may begin running this build. If not enqueued, it is up to the client to
	// run the build and update it accordingly.
	Queue bool
}

var ErrBuildNotFound = errors.New("build not found")

type BuildGetOptions struct{}

func (s *buildsService) Get(build BuildSpec, opt *BuildGetOptions) (*Build, Response, error) {
	url, err := s.client.url(api_router.Build, build.RouteVars(), opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var build_ *Build
	resp, err := s.client.Do(req, &build_)
	if err != nil {
		return nil, resp, err
	}

	return build_, nil, nil
}

type BuildListOptions struct {
	Queued    bool `url:",omitempty"`
	Ended     bool `url:",omitempty"`
	Succeeded bool `url:",omitempty"`

	ListOptions
}

func (s *buildsService) List(opt *BuildListOptions) ([]*Build, Response, error) {
	url, err := s.client.url(api_router.Builds, nil, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var builds []*Build
	resp, err := s.client.Do(req, &builds)
	if err != nil {
		return nil, resp, err
	}

	return builds, resp, nil
}

type BuildListByRepositoryOptions struct {
	BuildListOptions
	Rev string `url:",omitempty"`
}

func (s *buildsService) ListByRepository(repo RepositorySpec, opt *BuildListByRepositoryOptions) ([]*Build, Response, error) {
	url, err := s.client.url(api_router.RepositoryBuilds, map[string]string{"RepoURI": repo.URI}, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var builds []*Build
	resp, err := s.client.Do(req, &builds)
	if err != nil {
		return nil, resp, err
	}

	return builds, resp, nil
}

func (s *buildsService) Create(repo RepositorySpec, conf BuildConfig) (*Build, Response, error) {
	url, err := s.client.url(api_router.RepositoryBuildsCreate, repo.RouteVars(), nil)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("POST", url.String(), conf)
	if err != nil {
		return nil, nil, err
	}

	var build *Build
	resp, err := s.client.Do(req, &build)
	if err != nil {
		return nil, resp, err
	}

	return build, resp, nil
}

type BuildTaskListOptions struct{ ListOptions }

func (s *buildsService) ListBuildTasks(build BuildSpec, opt *BuildTaskListOptions) ([]*BuildTask, Response, error) {
	url, err := s.client.url(api_router.BuildTasks, build.RouteVars(), opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var tasks []*BuildTask
	resp, err := s.client.Do(req, &tasks)
	if err != nil {
		return nil, resp, err
	}

	return tasks, resp, nil
}

type MockBuildsService struct {
	Get_              func(build BuildSpec, opt *BuildGetOptions) (*Build, Response, error)
	List_             func(opt *BuildListOptions) ([]*Build, Response, error)
	ListByRepository_ func(repo RepositorySpec, opt *BuildListByRepositoryOptions) ([]*Build, Response, error)
	Create_           func(repo RepositorySpec, conf BuildConfig) (*Build, Response, error)
	ListBuildTasks_   func(build BuildSpec, opt *BuildTaskListOptions) ([]*BuildTask, Response, error)
}

var _ BuildsService = MockBuildsService{}

func (s MockBuildsService) Get(build BuildSpec, opt *BuildGetOptions) (*Build, Response, error) {
	if s.Get_ == nil {
		return nil, &HTTPResponse{}, nil
	}
	return s.Get_(build, opt)
}

func (s MockBuildsService) List(opt *BuildListOptions) ([]*Build, Response, error) {
	if s.List_ == nil {
		return nil, nil, nil
	}
	return s.List_(opt)
}

func (s MockBuildsService) ListByRepository(repo RepositorySpec, opt *BuildListByRepositoryOptions) ([]*Build, Response, error) {
	if s.ListByRepository_ == nil {
		return nil, &HTTPResponse{}, nil
	}
	return s.ListByRepository_(repo, opt)
}

func (s MockBuildsService) Create(repo RepositorySpec, conf BuildConfig) (*Build, Response, error) {
	if s.Create_ == nil {
		return nil, nil, nil
	}
	return s.Create_(repo, conf)
}

func (s MockBuildsService) ListBuildTasks(build BuildSpec, opt *BuildTaskListOptions) ([]*BuildTask, Response, error) {
	if s.ListBuildTasks_ == nil {
		return nil, nil, nil
	}
	return s.ListBuildTasks_(build, opt)
}
<commit_msg>build log url<commit_after>package client

import (
	"errors"
	"fmt"
	"time"

	"strconv"

	"sourcegraph.com/sourcegraph/api_router"
	"sourcegraph.com/sourcegraph/srcgraph/db_common"
	"sourcegraph.com/sourcegraph/srcgraph/repo"
	"sourcegraph.com/sourcegraph/srcgraph/task2"
)

// BuildsService communicates with the build-related endpoints in the
// Sourcegraph API.
type BuildsService interface {
	// Get fetches a build.
	Get(build BuildSpec, opt *BuildGetOptions) (*Build, Response, error)

	// List builds.
	List(opt *BuildListOptions) ([]*Build, Response, error)

	// ListByRepository lists builds for a repository.
	ListByRepository(repo RepositorySpec, opt *BuildListByRepositoryOptions) ([]*Build, Response, error)

	// Create a new build. The build will run asynchronously (Create does not
	// wait for it to return. To monitor the build's status, use Get.)
	Create(repo RepositorySpec, conf BuildConfig) (*Build, Response, error)

	// ListBuildTasks lists the tasks associated with a build.
	ListBuildTasks(build BuildSpec, opt *BuildTaskListOptions) ([]*BuildTask, Response, error)
}

type buildsService struct {
	client *Client
}

var _ BuildsService = &buildsService{}

type BuildSpec struct {
	BID int64
}

func (s *BuildSpec) RouteVars() map[string]string {
	return map[string]string{"BID": fmt.Sprintf("%d", s.BID)}
}

// A Build represents a scheduled, completed, or failed repository analysis and
// import job.
type Build struct {
	BID       int64
	Repo      repo.RID
	CommitID  string             `db:"commit_id"`
	CreatedAt time.Time          `db:"created_at"`
	StartedAt db_common.NullTime `db:"started_at"`
	EndedAt   db_common.NullTime `db:"ended_at"`
	Success   bool
	Failure   bool

	BuildConfig

	// RepoURI is populated (as a convenience) in results by Get and List but
	// should not be set when creating builds (it will be ignored).
	RepoURI repo.URI `db:"repo_uri" json:",omitempty"`
}

// IDString returns a succinct string that uniquely identifies this build.
func (b *Build) IDString() string { return buildIDString(b.BID) }

func buildIDString(bid int64) string { return "B" + strconv.FormatInt(bid, 36) }

// LogURL is the URL to the logs for this build.
func (b *Build) LogURL() string {
	return task2.LogURLForTag(b.IDString())
}

// A BuildTask represents an individual step of a build.
type BuildTask struct {
	TID int64

	// BID is the build that this task is a part of.
	BID int64

	UnitType string
	Unit     string

	Title string

	StartedAt db_common.NullTime `db:"started_at"`
	EndedAt   db_common.NullTime `db:"ended_at"`

	Success bool
	Failure bool
}

// IDString returns a succinct string that uniquely identifies this build task.
func (t *BuildTask) IDString() string {
	return buildIDString(t.BID) + "-T" + strconv.FormatInt(t.TID, 36)
}

// LogURL is the URL to the logs for this task.
func (t *BuildTask) LogURL() string {
	return task2.LogURLForTag(t.IDString())
}

// BuildConfig configures a repository build.
type BuildConfig struct {
	// Import is whether to import the build data into the database when the
	// build is complete. The data must be imported for Sourcegraph's web app or
	// API to use it, except that unimported build data is available through the
	// BuildData service. (TODO(sqs): BuildData isn't yet implemented.)
	Import bool

	// Queue is whether this build should be enqueued. If enqueued, any worker
	// may begin running this build. If not enqueued, it is up to the client to
	// run the build and update it accordingly.
	Queue bool
}

var ErrBuildNotFound = errors.New("build not found")

type BuildGetOptions struct{}

func (s *buildsService) Get(build BuildSpec, opt *BuildGetOptions) (*Build, Response, error) {
	url, err := s.client.url(api_router.Build, build.RouteVars(), opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var build_ *Build
	resp, err := s.client.Do(req, &build_)
	if err != nil {
		return nil, resp, err
	}

	return build_, nil, nil
}

type BuildListOptions struct {
	Queued    bool `url:",omitempty"`
	Ended     bool `url:",omitempty"`
	Succeeded bool `url:",omitempty"`

	ListOptions
}

func (s *buildsService) List(opt *BuildListOptions) ([]*Build, Response, error) {
	url, err := s.client.url(api_router.Builds, nil, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var builds []*Build
	resp, err := s.client.Do(req, &builds)
	if err != nil {
		return nil, resp, err
	}

	return builds, resp, nil
}

type BuildListByRepositoryOptions struct {
	BuildListOptions
	Rev string `url:",omitempty"`
}

func (s *buildsService) ListByRepository(repo RepositorySpec, opt *BuildListByRepositoryOptions) ([]*Build, Response, error) {
	url, err := s.client.url(api_router.RepositoryBuilds, map[string]string{"RepoURI": repo.URI}, opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var builds []*Build
	resp, err := s.client.Do(req, &builds)
	if err != nil {
		return nil, resp, err
	}

	return builds, resp, nil
}

func (s *buildsService) Create(repo RepositorySpec, conf BuildConfig) (*Build, Response, error) {
	url, err := s.client.url(api_router.RepositoryBuildsCreate, repo.RouteVars(), nil)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("POST", url.String(), conf)
	if err != nil {
		return nil, nil, err
	}

	var build *Build
	resp, err := s.client.Do(req, &build)
	if err != nil {
		return nil, resp, err
	}

	return build, resp, nil
}

type BuildTaskListOptions struct{ ListOptions }

func (s *buildsService) ListBuildTasks(build BuildSpec, opt *BuildTaskListOptions) ([]*BuildTask, Response, error) {
	url, err := s.client.url(api_router.BuildTasks, build.RouteVars(), opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var tasks []*BuildTask
	resp, err := s.client.Do(req, &tasks)
	if err != nil {
		return nil, resp, err
	}

	return tasks, resp, nil
}

type MockBuildsService struct {
	Get_              func(build BuildSpec, opt *BuildGetOptions) (*Build, Response, error)
	List_             func(opt *BuildListOptions) ([]*Build, Response, error)
	ListByRepository_ func(repo RepositorySpec, opt *BuildListByRepositoryOptions) ([]*Build, Response, error)
	Create_           func(repo RepositorySpec, conf BuildConfig) (*Build, Response, error)
	ListBuildTasks_   func(build BuildSpec, opt *BuildTaskListOptions) ([]*BuildTask, Response, error)
}

var _ BuildsService = MockBuildsService{}

func (s MockBuildsService) Get(build BuildSpec, opt *BuildGetOptions) (*Build, Response, error) {
	if s.Get_ == nil {
		return nil, &HTTPResponse{}, nil
	}
	return s.Get_(build, opt)
}

func (s MockBuildsService) List(opt *BuildListOptions) ([]*Build, Response, error) {
	if s.List_ == nil {
		return nil, nil, nil
	}
	return s.List_(opt)
}

func (s MockBuildsService) ListByRepository(repo RepositorySpec, opt *BuildListByRepositoryOptions) ([]*Build, Response, error) {
	if s.ListByRepository_ == nil {
		return nil, &HTTPResponse{}, nil
	}
	return s.ListByRepository_(repo, opt)
}

func (s MockBuildsService) Create(repo RepositorySpec, conf BuildConfig) (*Build, Response, error) {
	if s.Create_ == nil {
		return nil, nil, nil
	}
	return s.Create_(repo, conf)
}

func (s MockBuildsService) ListBuildTasks(build BuildSpec, opt *BuildTaskListOptions) ([]*BuildTask, Response, error) {
	if s.ListBuildTasks_ == nil {
		return nil, nil, nil
	}
	return s.ListBuildTasks_(build, opt)
}
<|endoftext|>


<commit_before>/***************************************************************************
 Copyright 2017 William Knox Carey

 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 beacon

// Specific implementations for version 0.3 beacons

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Type alias for this version
type beaconV3 beaconStruct

// Register this version's type
func init() {
	var nilStruct *beaconV3
	beaconType["0.3"] = reflect.TypeOf(nilStruct).Elem()
}

// Initialize the beacon with defaults appropriate for this version
func (beacon *beaconV3) initialize() {
	beacon.QueryMap = make(map[string]string)
	beacon.QueryMap["chromosome"]     = "chromosome"
	beacon.QueryMap["start"]          = "start"
	beacon.QueryMap["alternateBases"] = "alternateBases"
	beacon.QueryMap["referenceBases"] = "referenceBases"
	beacon.QueryMap["datasetIds"]     = "datasetIds"
	beacon.QueryMap["assemblyId"]     = "assemblyId"
	beacon.QueryMap["GRCh37"]         = "GRCh37"
	beacon.QueryMap["GRCh38"]         = "GRCh38"
}

func (beacon *beaconV3) parseResponse(status int, raw []byte, err error) *BeaconResponse {
	response := &BeaconResponse{Name: beacon.Name,
		Icon: beacon.Icon,
		Responses: make(map[string]string),
		Error: make(map[string]string)}

	if err != nil {
		addResponseError(response, 400, "could not reach beacon")
		return response
	}

	if status/100 != 2 {
		addResponseError(response, status, "beacon error")
		return response
	}

	// var v3 struct {
	// 	DatasetIds              []string
	// 	DatasetAlleleResponses  []map[string]string
	// 	Error                   map[string]string
	// 	Exists                  string}

	var v3 struct {
		BeaconId                string                    `json:"beaconId"`
		Exists                  bool                      `json:"exists"`
		Error                   map[string]string         `json:"error,omitempty"`
		AlleleRequest           map [string]interface{}   `json:"alleleRequest,omitempty"`
		DatasetAlleleResponses  []map[string]interface{}  `json:"datasetAlleleResponses,omitempty"`
	}

	if err := json.Unmarshal(raw, &v3); err == nil {
		if v3.Error == nil {
			response.Status = status
			for _, r := range v3.DatasetAlleleResponses {
				var ex string
				if r["exists"].(bool) {
					ex = "true"
				} else {
					ex = "false"
				}

				id := r["datasetId"].(string)
				addResponseResult(response, id, ex)
			}
		} else {
			code, _ := strconv.Atoi(v3.Error["errorCode"])
			addResponseError(response, code, v3.Error["message"])
		}
	} else {
		addResponseError(response, 400, "malformed reply from beacon")
	}

	return response
}

func (beacon *beaconV3) query(query *BeaconQuery, accessToken string, idToken string, ch chan<- BeaconResponse) {
	qs := beacon.queryString(query)
	uri := fmt.Sprintf("%s?%s", beacon.Endpoint, qs)

	status, body, err := httpGet(uri, accessToken, idToken)
	resp := beacon.parseResponse(status, body, err)

	ch <- *resp
}

// Construct the query string
func (beacon *beaconV3) queryString(query *BeaconQuery) string {
	ql := make([]string, 0, 20)

	for _, d := range beacon.DatasetIds {
		ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap["datasetIds"], d))
	}

	for k, v := range *query {
		if k == "assemblyId" {
			ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap[k], beacon.QueryMap[v[0]]))
		} else {
			ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap[k], v[0]))
		}
	}

	for k2, v2 := range beacon.AdditionalFields {
		ql = append(ql, fmt.Sprintf("%s=%s", k2, v2))
	}

	return strings.Join(ql, "&")
}

<commit_msg>Cleanup<commit_after>/***************************************************************************
 Copyright 2017 William Knox Carey

 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 beacon

// Specific implementations for version 0.3 beacons

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Type alias for this version
type beaconV3 beaconStruct

// Register this version's type
func init() {
	var nilStruct *beaconV3
	beaconType["0.3"] = reflect.TypeOf(nilStruct).Elem()
}

// Initialize the beacon with defaults appropriate for this version
func (beacon *beaconV3) initialize() {
	beacon.QueryMap = make(map[string]string)
	beacon.QueryMap["chromosome"]     = "chromosome"
	beacon.QueryMap["start"]          = "start"
	beacon.QueryMap["alternateBases"] = "alternateBases"
	beacon.QueryMap["referenceBases"] = "referenceBases"
	beacon.QueryMap["datasetIds"]     = "datasetIds"
	beacon.QueryMap["assemblyId"]     = "assemblyId"
	beacon.QueryMap["GRCh37"]         = "GRCh37"
	beacon.QueryMap["GRCh38"]         = "GRCh38"
}

func (beacon *beaconV3) parseResponse(status int, raw []byte, err error) *BeaconResponse {
	response := &BeaconResponse{Name: beacon.Name,
		Icon: beacon.Icon,
		Responses: make(map[string]string),
		Error: make(map[string]string)}

	if err != nil {
		addResponseError(response, 400, "could not reach beacon")
		return response
	}

	if status/100 != 2 {
		addResponseError(response, status, "beacon error")
		return response
	}

	var v3 struct {
		BeaconId                string                    `json:"beaconId"`
		Exists                  bool                      `json:"exists"`
		Error                   map[string]string         `json:"error,omitempty"`
		AlleleRequest           map [string]interface{}   `json:"alleleRequest,omitempty"`
		DatasetAlleleResponses  []map[string]interface{}  `json:"datasetAlleleResponses,omitempty"`
	}

	if err := json.Unmarshal(raw, &v3); err == nil {
		if v3.Error == nil {
			response.Status = status
			for _, r := range v3.DatasetAlleleResponses {
				var ex string
				if r["exists"].(bool) {
					ex = "true"
				} else {
					ex = "false"
				}

				id := r["datasetId"].(string)
				addResponseResult(response, id, ex)
			}
		} else {
			code, _ := strconv.Atoi(v3.Error["errorCode"])
			addResponseError(response, code, v3.Error["message"])
		}
	} else {
		addResponseError(response, 400, "malformed reply from beacon")
	}

	return response
}

func (beacon *beaconV3) query(query *BeaconQuery, accessToken string, idToken string, ch chan<- BeaconResponse) {
	qs := beacon.queryString(query)
	uri := fmt.Sprintf("%s?%s", beacon.Endpoint, qs)

	status, body, err := httpGet(uri, accessToken, idToken)
	resp := beacon.parseResponse(status, body, err)

	ch <- *resp
}

// Construct the query string
func (beacon *beaconV3) queryString(query *BeaconQuery) string {
	ql := make([]string, 0, 20)

	for _, d := range beacon.DatasetIds {
		ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap["datasetIds"], d))
	}

	for k, v := range *query {
		if k == "assemblyId" {
			ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap[k], beacon.QueryMap[v[0]]))
		} else {
			ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap[k], v[0]))
		}
	}

	for k2, v2 := range beacon.AdditionalFields {
		ql = append(ql, fmt.Sprintf("%s=%s", k2, v2))
	}

	return strings.Join(ql, "&")
}

<|endoftext|>


<commit_before>package client

import (
	"github.com/dotcloud/docker/rcli"
	"github.com/dotcloud/docker/future"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
)

// Run docker in "simple mode": run a single command and return.
func SimpleMode(args []string) error {
	var oldState *State
	var err error
	if IsTerminal(0) && os.Getenv("NORAW") == "" {
		oldState, err = MakeRaw(0)
		if err != nil {
			return err
		}
		defer Restore(0, oldState)
	}
	// FIXME: we want to use unix sockets here, but net.UnixConn doesn't expose
	// CloseWrite(), which we need to cleanly signal that stdin is closed without
	// closing the connection.
	// See http://code.google.com/p/go/issues/detail?id=3345
	conn, err := rcli.Call("tcp", "127.0.0.1:4242", args...)
	if err != nil {
		return err
	}
	receive_stdout := future.Go(func() error {
		_, err := io.Copy(os.Stdout, conn)
		return err
	})
	send_stdin := future.Go(func() error {
		_, err := io.Copy(conn, os.Stdin)
		if err := conn.CloseWrite(); err != nil {
			log.Printf("Couldn't send EOF: " + err.Error())
		}
		return err
	})
	if err := <-receive_stdout; err != nil {
		return err
	}
	if oldState != nil {
		Restore(0, oldState)
	}
	if !IsTerminal(0) {
		if err := <-send_stdin; err != nil {
			return err
		}
	}
	return nil
}

// Run docker in "interactive mode": run a bash-compatible shell capable of running docker commands.
func InteractiveMode(scripts ...string) error {
	// Determine path of current docker binary
	dockerPath, err := exec.LookPath(os.Args[0])
	if err != nil {
		return err
	}
	dockerPath, err = filepath.Abs(dockerPath)
	if err != nil {
		return err
	}

	// Create a temp directory
	tmp, err := ioutil.TempDir("", "docker-shell")
	if err != nil {
		return err
	}
	defer os.RemoveAll(tmp)

	// For each command, create an alias in temp directory
	// FIXME: generate this list dynamically with introspection of some sort
	// It might make sense to merge docker and dockerd to keep that introspection
	// within a single binary.
	for _, cmd := range []string{
		"help",
		"run",
		"ps",
		"pull",
		"put",
		"rm",
		"kill",
		"wait",
		"stop",
		"logs",
		"diff",
		"commit",
		"attach",
		"info",
		"tar",
		"web",
		"images",
		"docker",
	} {
		if err := os.Symlink(dockerPath, path.Join(tmp, cmd)); err != nil {
			return err
		}
	}

	// Run $SHELL with PATH set to temp directory
	rcfile, err := ioutil.TempFile("", "docker-shell-rc")
	if err != nil {
		return err
	}
	io.WriteString(rcfile, "enable -n help\n")
	os.Setenv("PATH", tmp)
	os.Setenv("PS1", "\\h docker> ")
	shell := exec.Command("/bin/bash", append([]string{"--rcfile", rcfile.Name()}, scripts...)...)
	shell.Stdin = os.Stdin
	shell.Stdout = os.Stdout
	shell.Stderr = os.Stderr
	if err := shell.Run(); err != nil {
		return err
	}
	return nil
}
<commit_msg>'docker start' and 'docker restart': start or restart a container<commit_after>package client

import (
	"github.com/dotcloud/docker/rcli"
	"github.com/dotcloud/docker/future"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
)

// Run docker in "simple mode": run a single command and return.
func SimpleMode(args []string) error {
	var oldState *State
	var err error
	if IsTerminal(0) && os.Getenv("NORAW") == "" {
		oldState, err = MakeRaw(0)
		if err != nil {
			return err
		}
		defer Restore(0, oldState)
	}
	// FIXME: we want to use unix sockets here, but net.UnixConn doesn't expose
	// CloseWrite(), which we need to cleanly signal that stdin is closed without
	// closing the connection.
	// See http://code.google.com/p/go/issues/detail?id=3345
	conn, err := rcli.Call("tcp", "127.0.0.1:4242", args...)
	if err != nil {
		return err
	}
	receive_stdout := future.Go(func() error {
		_, err := io.Copy(os.Stdout, conn)
		return err
	})
	send_stdin := future.Go(func() error {
		_, err := io.Copy(conn, os.Stdin)
		if err := conn.CloseWrite(); err != nil {
			log.Printf("Couldn't send EOF: " + err.Error())
		}
		return err
	})
	if err := <-receive_stdout; err != nil {
		return err
	}
	if oldState != nil {
		Restore(0, oldState)
	}
	if !IsTerminal(0) {
		if err := <-send_stdin; err != nil {
			return err
		}
	}
	return nil
}

// Run docker in "interactive mode": run a bash-compatible shell capable of running docker commands.
func InteractiveMode(scripts ...string) error {
	// Determine path of current docker binary
	dockerPath, err := exec.LookPath(os.Args[0])
	if err != nil {
		return err
	}
	dockerPath, err = filepath.Abs(dockerPath)
	if err != nil {
		return err
	}

	// Create a temp directory
	tmp, err := ioutil.TempDir("", "docker-shell")
	if err != nil {
		return err
	}
	defer os.RemoveAll(tmp)

	// For each command, create an alias in temp directory
	// FIXME: generate this list dynamically with introspection of some sort
	// It might make sense to merge docker and dockerd to keep that introspection
	// within a single binary.
	for _, cmd := range []string{
		"help",
		"run",
		"ps",
		"pull",
		"put",
		"rm",
		"kill",
		"wait",
		"stop",
		"start",
		"restart",
		"logs",
		"diff",
		"commit",
		"attach",
		"info",
		"tar",
		"web",
		"images",
		"docker",
	} {
		if err := os.Symlink(dockerPath, path.Join(tmp, cmd)); err != nil {
			return err
		}
	}

	// Run $SHELL with PATH set to temp directory
	rcfile, err := ioutil.TempFile("", "docker-shell-rc")
	if err != nil {
		return err
	}
	io.WriteString(rcfile, "enable -n help\n")
	os.Setenv("PATH", tmp)
	os.Setenv("PS1", "\\h docker> ")
	shell := exec.Command("/bin/bash", append([]string{"--rcfile", rcfile.Name()}, scripts...)...)
	shell.Stdin = os.Stdin
	shell.Stdout = os.Stdout
	shell.Stderr = os.Stderr
	if err := shell.Run(); err != nil {
		return err
	}
	return nil
}
<|endoftext|>