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

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"syscall"

	"github.com/coreos/go-systemd/daemon"
	"github.com/jessevdk/go-flags"
	"github.com/kr/pretty"
	log "github.com/sirupsen/logrus"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"

	api "github.com/osrg/gobgp/api"
	internal_cfg "github.com/osrg/gobgp/internal/pkg/config"
	"github.com/osrg/gobgp/internal/pkg/version"
	"github.com/osrg/gobgp/pkg/config"
	"github.com/osrg/gobgp/pkg/server"
)

func main() {
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGTERM)

	var opts struct {
		ConfigFile      string `short:"f" long:"config-file" description:"specifying a config file"`
		ConfigType      string `short:"t" long:"config-type" description:"specifying config type (toml, yaml, json)" default:"toml"`
		LogLevel        string `short:"l" long:"log-level" description:"specifying log level"`
		LogPlain        bool   `short:"p" long:"log-plain" description:"use plain format for logging (json by default)"`
		UseSyslog       string `short:"s" long:"syslog" description:"use syslogd"`
		Facility        string `long:"syslog-facility" description:"specify syslog facility"`
		DisableStdlog   bool   `long:"disable-stdlog" description:"disable standard logging"`
		CPUs            int    `long:"cpus" description:"specify the number of CPUs to be used"`
		GrpcHosts       string `long:"api-hosts" description:"specify the hosts that gobgpd listens on" default:":50051"`
		GracefulRestart bool   `short:"r" long:"graceful-restart" description:"flag restart-state in graceful-restart capability"`
		Dry             bool   `short:"d" long:"dry-run" description:"check configuration"`
		PProfHost       string `long:"pprof-host" description:"specify the host that gobgpd listens on for pprof" default:"localhost:6060"`
		PProfDisable    bool   `long:"pprof-disable" description:"disable pprof profiling"`
		UseSdNotify     bool   `long:"sdnotify" description:"use sd_notify protocol"`
		TLS             bool   `long:"tls" description:"enable TLS authentication for gRPC API"`
		TLSCertFile     string `long:"tls-cert-file" description:"The TLS cert file"`
		TLSKeyFile      string `long:"tls-key-file" description:"The TLS key file"`
		Version         bool   `long:"version" description:"show version number"`
	}
	_, err := flags.Parse(&opts)
	if err != nil {
		os.Exit(1)
	}

	if opts.Version {
		fmt.Println("gobgpd version", version.Version())
		os.Exit(0)
	}

	if opts.CPUs == 0 {
		runtime.GOMAXPROCS(runtime.NumCPU())
	} else {
		if runtime.NumCPU() < opts.CPUs {
			log.Errorf("Only %d CPUs are available but %d is specified", runtime.NumCPU(), opts.CPUs)
			os.Exit(1)
		}
		runtime.GOMAXPROCS(opts.CPUs)
	}

	if !opts.PProfDisable {
		go func() {
			log.Println(http.ListenAndServe(opts.PProfHost, nil))
		}()
	}

	switch opts.LogLevel {
	case "debug":
		log.SetLevel(log.DebugLevel)
	case "info":
		log.SetLevel(log.InfoLevel)
	default:
		log.SetLevel(log.InfoLevel)
	}

	if opts.DisableStdlog {
		log.SetOutput(ioutil.Discard)
	} else {
		log.SetOutput(os.Stdout)
	}

	if opts.UseSyslog != "" {
		if err := addSyslogHook(opts.UseSyslog, opts.Facility); err != nil {
			log.Error("Unable to connect to syslog daemon, ", opts.UseSyslog)
		}
	}

	if opts.LogPlain {
		if opts.DisableStdlog {
			log.SetFormatter(&log.TextFormatter{
				DisableColors: true,
			})
		}
	} else {
		log.SetFormatter(&log.JSONFormatter{})
	}

	configCh := make(chan *internal_cfg.BgpConfigSet)
	if opts.Dry {
		go internal_cfg.ReadConfigfileServe(opts.ConfigFile, opts.ConfigType, configCh)
		c := <-configCh
		if opts.LogLevel == "debug" {
			pretty.Println(c)
		}
		os.Exit(0)
	}

	maxSize := 256 << 20
	grpcOpts := []grpc.ServerOption{grpc.MaxRecvMsgSize(maxSize), grpc.MaxSendMsgSize(maxSize)}
	if opts.TLS {
		creds, err := credentials.NewServerTLSFromFile(opts.TLSCertFile, opts.TLSKeyFile)
		if err != nil {
			log.Fatalf("Failed to generate credentials: %v", err)
		}
		grpcOpts = append(grpcOpts, grpc.Creds(creds))
	}

	log.Info("gobgpd started")
	bgpServer := server.NewBgpServer(server.GrpcListenAddress(opts.GrpcHosts), server.GrpcOption(grpcOpts))
	go bgpServer.Serve()

	if opts.UseSdNotify {
		if status, err := daemon.SdNotify(false, daemon.SdNotifyReady); !status {
			if err != nil {
				log.Warnf("Failed to send notification via sd_notify(): %s", err)
			} else {
				log.Warnf("The socket sd_notify() isn't available")
			}
		}
	}

	if opts.ConfigFile != "" {
		go internal_cfg.ReadConfigfileServe(opts.ConfigFile, opts.ConfigType, configCh)
	}

	loop := func() {
		initialConfig := <-configCh
		c := config.ApplyInitialConfig(bgpServer, initialConfig, opts.GracefulRestart)
		for {
			select {
			case <-sigCh:
				stopServer(bgpServer, opts.UseSdNotify)
				return
			case newConfig := <-configCh:
				c = config.UpdateConfig(bgpServer, c, newConfig)
			}
		}
	}

	loop()
}

func stopServer(bgpServer *server.BgpServer, useSdNotify bool) {
	bgpServer.StopBgp(context.Background(), &api.StopBgpRequest{})
	if useSdNotify {
		daemon.SdNotify(false, daemon.SdNotifyStopping)
	}
}
<commit_msg>Split creation of config reading channel<commit_after>//
// Copyright (C) 2014-2017 Nippon Telegraph and Telephone Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"syscall"

	"github.com/coreos/go-systemd/daemon"
	"github.com/jessevdk/go-flags"
	"github.com/kr/pretty"
	log "github.com/sirupsen/logrus"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"

	api "github.com/osrg/gobgp/api"
	internal_cfg "github.com/osrg/gobgp/internal/pkg/config"
	"github.com/osrg/gobgp/internal/pkg/version"
	"github.com/osrg/gobgp/pkg/config"
	"github.com/osrg/gobgp/pkg/server"
)

func main() {
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGTERM)

	var opts struct {
		ConfigFile      string `short:"f" long:"config-file" description:"specifying a config file"`
		ConfigType      string `short:"t" long:"config-type" description:"specifying config type (toml, yaml, json)" default:"toml"`
		LogLevel        string `short:"l" long:"log-level" description:"specifying log level"`
		LogPlain        bool   `short:"p" long:"log-plain" description:"use plain format for logging (json by default)"`
		UseSyslog       string `short:"s" long:"syslog" description:"use syslogd"`
		Facility        string `long:"syslog-facility" description:"specify syslog facility"`
		DisableStdlog   bool   `long:"disable-stdlog" description:"disable standard logging"`
		CPUs            int    `long:"cpus" description:"specify the number of CPUs to be used"`
		GrpcHosts       string `long:"api-hosts" description:"specify the hosts that gobgpd listens on" default:":50051"`
		GracefulRestart bool   `short:"r" long:"graceful-restart" description:"flag restart-state in graceful-restart capability"`
		Dry             bool   `short:"d" long:"dry-run" description:"check configuration"`
		PProfHost       string `long:"pprof-host" description:"specify the host that gobgpd listens on for pprof" default:"localhost:6060"`
		PProfDisable    bool   `long:"pprof-disable" description:"disable pprof profiling"`
		UseSdNotify     bool   `long:"sdnotify" description:"use sd_notify protocol"`
		TLS             bool   `long:"tls" description:"enable TLS authentication for gRPC API"`
		TLSCertFile     string `long:"tls-cert-file" description:"The TLS cert file"`
		TLSKeyFile      string `long:"tls-key-file" description:"The TLS key file"`
		Version         bool   `long:"version" description:"show version number"`
	}
	_, err := flags.Parse(&opts)
	if err != nil {
		os.Exit(1)
	}

	if opts.Version {
		fmt.Println("gobgpd version", version.Version())
		os.Exit(0)
	}

	if opts.CPUs == 0 {
		runtime.GOMAXPROCS(runtime.NumCPU())
	} else {
		if runtime.NumCPU() < opts.CPUs {
			log.Errorf("Only %d CPUs are available but %d is specified", runtime.NumCPU(), opts.CPUs)
			os.Exit(1)
		}
		runtime.GOMAXPROCS(opts.CPUs)
	}

	if !opts.PProfDisable {
		go func() {
			log.Println(http.ListenAndServe(opts.PProfHost, nil))
		}()
	}

	switch opts.LogLevel {
	case "debug":
		log.SetLevel(log.DebugLevel)
	case "info":
		log.SetLevel(log.InfoLevel)
	default:
		log.SetLevel(log.InfoLevel)
	}

	if opts.DisableStdlog {
		log.SetOutput(ioutil.Discard)
	} else {
		log.SetOutput(os.Stdout)
	}

	if opts.UseSyslog != "" {
		if err := addSyslogHook(opts.UseSyslog, opts.Facility); err != nil {
			log.Error("Unable to connect to syslog daemon, ", opts.UseSyslog)
		}
	}

	if opts.LogPlain {
		if opts.DisableStdlog {
			log.SetFormatter(&log.TextFormatter{
				DisableColors: true,
			})
		}
	} else {
		log.SetFormatter(&log.JSONFormatter{})
	}

	if opts.Dry {
		configCh := make(chan *internal_cfg.BgpConfigSet)
		go internal_cfg.ReadConfigfileServe(opts.ConfigFile, opts.ConfigType, configCh)
		c := <-configCh
		if opts.LogLevel == "debug" {
			pretty.Println(c)
		}
		os.Exit(0)
	}

	maxSize := 256 << 20
	grpcOpts := []grpc.ServerOption{grpc.MaxRecvMsgSize(maxSize), grpc.MaxSendMsgSize(maxSize)}
	if opts.TLS {
		creds, err := credentials.NewServerTLSFromFile(opts.TLSCertFile, opts.TLSKeyFile)
		if err != nil {
			log.Fatalf("Failed to generate credentials: %v", err)
		}
		grpcOpts = append(grpcOpts, grpc.Creds(creds))
	}

	log.Info("gobgpd started")
	bgpServer := server.NewBgpServer(server.GrpcListenAddress(opts.GrpcHosts), server.GrpcOption(grpcOpts))
	go bgpServer.Serve()

	if opts.UseSdNotify {
		if status, err := daemon.SdNotify(false, daemon.SdNotifyReady); !status {
			if err != nil {
				log.Warnf("Failed to send notification via sd_notify(): %s", err)
			} else {
				log.Warnf("The socket sd_notify() isn't available")
			}
		}
	}

	if opts.ConfigFile == "" {
		<-sigCh
		stopServer(bgpServer, opts.UseSdNotify)
		return
	}

	configCh := make(chan *internal_cfg.BgpConfigSet)
	go internal_cfg.ReadConfigfileServe(opts.ConfigFile, opts.ConfigType, configCh)
	loop := func() {
		initialConfig := <-configCh
		c := config.ApplyInitialConfig(bgpServer, initialConfig, opts.GracefulRestart)
		for {
			select {
			case <-sigCh:
				stopServer(bgpServer, opts.UseSdNotify)
				return
			case newConfig := <-configCh:
				c = config.UpdateConfig(bgpServer, c, newConfig)
			}
		}
	}

	loop()
}

func stopServer(bgpServer *server.BgpServer, useSdNotify bool) {
	bgpServer.StopBgp(context.Background(), &api.StopBgpRequest{})
	if useSdNotify {
		daemon.SdNotify(false, daemon.SdNotifyStopping)
	}
}
<|endoftext|>


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

package main

import (
	"flag"
	"github.com/couchbase/gometa/server"
	"log"
	"os"
)

//
// main function
//
func main() {

	var isClient string
	var isWatcher string
	var config string
	flag.StringVar(&isClient, "client", "false", "run as test client")
	flag.StringVar(&isWatcher, "watcher", "false", "run as watcher")
	flag.StringVar(&config, "config", "", "path for configuration file")
	flag.Parse()

	if isClient == "true" {
		runTestClient(config)
		os.Exit(0)
	}

	if isWatcher == "true" {
		runWatcher(config)
		os.Exit(0)
	}

	err := server.RunServer(config)
	if err != nil {
		log.Printf("Encounter Error = %s. Terminate server", err.Error())
		os.Exit(1)
	}

	os.Exit(0)
}
<commit_msg>Use BoolVar for isWatcher -client and -watcher flags.<commit_after>// @author Couchbase <info@couchbase.com>
// @copyright 2014 Couchbase, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"flag"
	"github.com/couchbase/gometa/server"
	"log"
	"os"
)

//
// main function
//
func main() {
	var isClient bool
	var isWatcher bool
	var config string

	flag.BoolVar(&isClient, "client", false, "run as test client")
	flag.BoolVar(&isWatcher, "watcher", false, "run as watcher")
	flag.StringVar(&config, "config", "", "path for configuration file")
	flag.Parse()

	if isClient {
		runTestClient(config)
		os.Exit(0)
	}

	if isWatcher {
		runWatcher(config)
		os.Exit(0)
	}

	err := server.RunServer(config)
	if err != nil {
		log.Printf("Encounter Error = %s. Terminate server", err.Error())
		os.Exit(1)
	}

	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/sapcc/kubernikus/pkg/api/client/operations"
	"github.com/sapcc/kubernikus/pkg/api/models"
	"github.com/sapcc/kubernikus/test/e2e/framework"
)

const (
	KlusterPhaseBecomesCreatingTimeout = 1 * time.Minute
	KlusterPhaseBecomesRunningTimeout  = 15 * time.Minute
)

type SetupTests struct {
	Kubernikus  *framework.Kubernikus
	OpenStack   *framework.OpenStack
	KlusterName string
	Reuse       bool
}

func (s *SetupTests) Run(t *testing.T) {
	if s.Reuse == false {
		created := t.Run("Cluster/Create", s.CreateCluster)
		require.True(t, created, "The Kluster must have been created")

		t.Run("Cluster/BecomesCreating", s.KlusterPhaseBecomesCreating)
	}

	running := t.Run("Cluster/BecomesRunning", s.KlusterPhaseBecomesRunning)
	require.True(t, running, "The Kluster must be Running")
}

func (s *SetupTests) CreateCluster(t *testing.T) {
	version := "1.22.4"
	if v := os.Getenv("KLUSTER_VERSION"); v != "" {
		version = v
	}

	clusterCidr := "100.100.0.0/16"
	if cidr := os.Getenv("KLUSTER_CIDR"); cidr != "" {
		clusterCidr = cidr
	}

	osImages := []string{"flatcar-stable-amd64"}
	if image := os.Getenv("KLUSTER_OS_IMAGES"); image != "" {
		osImages = strings.Split(image, "")
	}
	require.LessOrEqual(t, len(osImages), SmokeTestNodeCount, "more os images then smoke test node specified")

	pools := []models.NodePool{}
	for i, image := range osImages {
		pools = append(pools, models.NodePool{
			Name:             fmt.Sprintf("pool%d", i+1),
			Flavor:           "c_c2_m2",
			Size:             1,
			AvailabilityZone: os.Getenv("NODEPOOL_AVZ"),
			Image:            image,
			Labels:           []string{"image=" + image},
		})
	}
	//we fill up the first pool in case the number of images is smaller then the  smoke test node count
	pools[0].Size = int64(SmokeTestNodeCount - len(pools) - 1)

	kluster := &models.Kluster{
		Name: s.KlusterName,
		Spec: models.KlusterSpec{
			Version:      version,
			SSHPublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCXIxVEUgtUVkvk2VM1hmIb8MxvxsmvYoiq9OBy3J8akTGNybqKsA2uhcwxSJX5Cn3si8kfMfka9EWiJT+e1ybvtsGILO5XRZPxyhYzexwb3TcALwc3LuzpF3Z/Dg2jYTRELTGhYmyca3mxzTlCjNXvYayLNedjJ8fIBzoCuSXNqDRToHru7h0Glz+wtuE74mNkOiXSvhtuJtJs7VCNVjobFQNfC1aeDsri2bPRHJJZJ0QF4LLYSayMEz3lVwIDyAviQR2Aa97WfuXiofiAemfGqiH47Kq6b8X7j3bOYGBvJKMUV7XeWhGsskAmTsvvnFxkc5PAD3Ct+liULjiQWlzDrmpTE8aMqLK4l0YQw7/8iRVz6gli42iEc2ZG56ob1ErpTLAKFWyCNOebZuGoygdEQaGTIIunAncXg5Rz07TdPl0Tf5ZZLpiAgR5ck0H1SETnjDTZ/S83CiVZWJgmCpu8YOKWyYRD4orWwdnA77L4+ixeojLIhEoNL8KlBgsP9Twx+fFMWLfxMmiuX+yksM6Hu+Lsm+Ao7Q284VPp36EB1rxP1JM7HCiEOEm50Jb6hNKjgN4aoLhG5yg+GnDhwCZqUwcRJo1bWtm3QvRA+rzrGZkId4EY3cyOK5QnYV5+24x93Ex0UspHMn7HGsHUESsVeV0fLqlfXyd2RbHTmDMP6w== Kubernikus Master Key",
			ClusterCIDR:  &clusterCidr,
			NodePools:    pools,
		},
	}

	cluster, err := s.Kubernikus.Client.Operations.CreateCluster(
		operations.NewCreateClusterParams().WithBody(kluster),
		s.Kubernikus.AuthInfo,
	)

	require.NoError(t, err, "There should be no error")
	require.NotNil(t, cluster.Payload, "There should be payload")
	assert.Equalf(t, s.KlusterName, cluster.Payload.Name, "There should be a kluster with name: %v", s.KlusterName)
	assert.Equal(t, cluster.Payload.Status.Phase, models.KlusterPhasePending, "Kluster should be in phase Pending")
}

func (s *SetupTests) KlusterPhaseBecomesCreating(t *testing.T) {
	phase, err := s.Kubernikus.WaitForKlusterPhase(s.KlusterName, models.KlusterPhaseCreating, KlusterPhaseBecomesCreatingTimeout)

	if assert.NoError(t, err, "There should be no error") {
		assert.Equal(t, phase, models.KlusterPhaseCreating, "Kluster should become Creating")
	}
}

func (s *SetupTests) KlusterPhaseBecomesRunning(t *testing.T) {
	phase, err := s.Kubernikus.WaitForKlusterPhase(s.KlusterName, models.KlusterPhaseRunning, KlusterPhaseBecomesRunningTimeout)

	if assert.NoError(t, err, "There should be no error") {
		require.Equal(t, phase, models.KlusterPhaseRunning, "Kluster should become Running")
	}
}
<commit_msg>Fix typo<commit_after>package main

import (
	"fmt"
	"os"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/sapcc/kubernikus/pkg/api/client/operations"
	"github.com/sapcc/kubernikus/pkg/api/models"
	"github.com/sapcc/kubernikus/test/e2e/framework"
)

const (
	KlusterPhaseBecomesCreatingTimeout = 1 * time.Minute
	KlusterPhaseBecomesRunningTimeout  = 15 * time.Minute
)

type SetupTests struct {
	Kubernikus  *framework.Kubernikus
	OpenStack   *framework.OpenStack
	KlusterName string
	Reuse       bool
}

func (s *SetupTests) Run(t *testing.T) {
	if s.Reuse == false {
		created := t.Run("Cluster/Create", s.CreateCluster)
		require.True(t, created, "The Kluster must have been created")

		t.Run("Cluster/BecomesCreating", s.KlusterPhaseBecomesCreating)
	}

	running := t.Run("Cluster/BecomesRunning", s.KlusterPhaseBecomesRunning)
	require.True(t, running, "The Kluster must be Running")
}

func (s *SetupTests) CreateCluster(t *testing.T) {
	version := "1.22.4"
	if v := os.Getenv("KLUSTER_VERSION"); v != "" {
		version = v
	}

	clusterCidr := "100.100.0.0/16"
	if cidr := os.Getenv("KLUSTER_CIDR"); cidr != "" {
		clusterCidr = cidr
	}

	osImages := []string{"flatcar-stable-amd64"}
	if image := os.Getenv("KLUSTER_OS_IMAGES"); image != "" {
		osImages = strings.Split(image, ",")
	}
	require.LessOrEqual(t, len(osImages), SmokeTestNodeCount, "more os images then smoke test node specified")

	pools := []models.NodePool{}
	for i, image := range osImages {
		pools = append(pools, models.NodePool{
			Name:             fmt.Sprintf("pool%d", i+1),
			Flavor:           "c_c2_m2",
			Size:             1,
			AvailabilityZone: os.Getenv("NODEPOOL_AVZ"),
			Image:            image,
			Labels:           []string{"image=" + image},
		})
	}
	//we fill up the first pool in case the number of images is smaller then the  smoke test node count
	pools[0].Size = int64(SmokeTestNodeCount - len(pools) - 1)

	kluster := &models.Kluster{
		Name: s.KlusterName,
		Spec: models.KlusterSpec{
			Version:      version,
			SSHPublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCXIxVEUgtUVkvk2VM1hmIb8MxvxsmvYoiq9OBy3J8akTGNybqKsA2uhcwxSJX5Cn3si8kfMfka9EWiJT+e1ybvtsGILO5XRZPxyhYzexwb3TcALwc3LuzpF3Z/Dg2jYTRELTGhYmyca3mxzTlCjNXvYayLNedjJ8fIBzoCuSXNqDRToHru7h0Glz+wtuE74mNkOiXSvhtuJtJs7VCNVjobFQNfC1aeDsri2bPRHJJZJ0QF4LLYSayMEz3lVwIDyAviQR2Aa97WfuXiofiAemfGqiH47Kq6b8X7j3bOYGBvJKMUV7XeWhGsskAmTsvvnFxkc5PAD3Ct+liULjiQWlzDrmpTE8aMqLK4l0YQw7/8iRVz6gli42iEc2ZG56ob1ErpTLAKFWyCNOebZuGoygdEQaGTIIunAncXg5Rz07TdPl0Tf5ZZLpiAgR5ck0H1SETnjDTZ/S83CiVZWJgmCpu8YOKWyYRD4orWwdnA77L4+ixeojLIhEoNL8KlBgsP9Twx+fFMWLfxMmiuX+yksM6Hu+Lsm+Ao7Q284VPp36EB1rxP1JM7HCiEOEm50Jb6hNKjgN4aoLhG5yg+GnDhwCZqUwcRJo1bWtm3QvRA+rzrGZkId4EY3cyOK5QnYV5+24x93Ex0UspHMn7HGsHUESsVeV0fLqlfXyd2RbHTmDMP6w== Kubernikus Master Key",
			ClusterCIDR:  &clusterCidr,
			NodePools:    pools,
		},
	}

	cluster, err := s.Kubernikus.Client.Operations.CreateCluster(
		operations.NewCreateClusterParams().WithBody(kluster),
		s.Kubernikus.AuthInfo,
	)

	require.NoError(t, err, "There should be no error")
	require.NotNil(t, cluster.Payload, "There should be payload")
	assert.Equalf(t, s.KlusterName, cluster.Payload.Name, "There should be a kluster with name: %v", s.KlusterName)
	assert.Equal(t, cluster.Payload.Status.Phase, models.KlusterPhasePending, "Kluster should be in phase Pending")
}

func (s *SetupTests) KlusterPhaseBecomesCreating(t *testing.T) {
	phase, err := s.Kubernikus.WaitForKlusterPhase(s.KlusterName, models.KlusterPhaseCreating, KlusterPhaseBecomesCreatingTimeout)

	if assert.NoError(t, err, "There should be no error") {
		assert.Equal(t, phase, models.KlusterPhaseCreating, "Kluster should become Creating")
	}
}

func (s *SetupTests) KlusterPhaseBecomesRunning(t *testing.T) {
	phase, err := s.Kubernikus.WaitForKlusterPhase(s.KlusterName, models.KlusterPhaseRunning, KlusterPhaseBecomesRunningTimeout)

	if assert.NoError(t, err, "There should be no error") {
		require.Equal(t, phase, models.KlusterPhaseRunning, "Kluster should become Running")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/influxdata/influxdb"
	"github.com/influxdata/influxdb/bolt"
	"github.com/influxdata/influxdb/cmd/influx/config"
	"github.com/influxdata/influxdb/cmd/influx/internal"
	"github.com/influxdata/influxdb/http"
	"github.com/influxdata/influxdb/internal/fs"
	"github.com/influxdata/influxdb/kit/cli"
	"github.com/influxdata/influxdb/kv"
	"github.com/influxdata/influxdb/pkg/httpc"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"go.uber.org/zap"
)

const maxTCPConnections = 128

func main() {
	influxCmd := influxCmd()
	if err := influxCmd.Execute(); err != nil {
		seeHelp(influxCmd, nil)
		os.Exit(1)
	}
}

var (
	httpClient *httpc.Client
)

func newHTTPClient() (*httpc.Client, error) {
	if httpClient != nil {
		return httpClient, nil
	}

	c, err := http.NewHTTPClient(flags.Host, flags.Token, flags.skipVerify)
	if err != nil {
		return nil, err
	}

	httpClient = c
	return httpClient, nil
}

type (
	cobraRunEFn func(cmd *cobra.Command, args []string) error

	cobraRunEMiddleware func(fn cobraRunEFn) cobraRunEFn

	genericCLIOptFn func(*genericCLIOpts)
)

type genericCLIOpts struct {
	in   io.Reader
	w    io.Writer
	errW io.Writer

	runEWrapFn cobraRunEMiddleware
}

func (o genericCLIOpts) newCmd(use string, runE func(*cobra.Command, []string) error, useRunEMiddleware bool) *cobra.Command {
	cmd := &cobra.Command{
		Args: cobra.NoArgs,
		Use:  use,
		RunE: runE,
	}

	canWrapRunE := runE != nil && o.runEWrapFn != nil
	if useRunEMiddleware && canWrapRunE {
		cmd.RunE = o.runEWrapFn(runE)
	} else if canWrapRunE {
		cmd.RunE = runE
	}

	cmd.SetOut(o.w)
	cmd.SetIn(o.in)
	cmd.SetErr(o.errW)
	return cmd
}

func (o genericCLIOpts) newTabWriter() *internal.TabWriter {
	return internal.NewTabWriter(o.w)
}

func in(r io.Reader) genericCLIOptFn {
	return func(o *genericCLIOpts) {
		o.in = r
	}
}

func out(w io.Writer) genericCLIOptFn {
	return func(o *genericCLIOpts) {
		o.w = w
	}
}

func err(w io.Writer) genericCLIOptFn {
	return func(o *genericCLIOpts) {
		o.errW = w
	}
}

func runEMiddlware(mw cobraRunEMiddleware) genericCLIOptFn {
	return func(o *genericCLIOpts) {
		o.runEWrapFn = mw
	}
}

type globalFlags struct {
	config.Config
	local      bool
	skipVerify bool
}

var flags globalFlags

type cmdInfluxBuilder struct {
	genericCLIOpts

	once sync.Once
}

func newInfluxCmdBuilder(optFns ...genericCLIOptFn) *cmdInfluxBuilder {
	builder := new(cmdInfluxBuilder)

	opt := genericCLIOpts{
		in:         os.Stdin,
		w:          os.Stdout,
		errW:       os.Stderr,
		runEWrapFn: checkSetupRunEMiddleware(&flags),
	}
	for _, optFn := range optFns {
		optFn(&opt)
	}

	builder.genericCLIOpts = opt
	return builder
}

func (b *cmdInfluxBuilder) cmd(childCmdFns ...func(f *globalFlags, opt genericCLIOpts) *cobra.Command) *cobra.Command {
	b.once.Do(func() {
		// enforce that viper options only ever get set once
		setViperOptions()
	})

	cmd := b.newCmd("influx", nil, false)
	cmd.Short = "Influx Client"
	cmd.SilenceUsage = true

	for _, childCmd := range childCmdFns {
		cmd.AddCommand(childCmd(&flags, b.genericCLIOpts))
	}

	fOpts := flagOpts{
		{
			DestP:      &flags.Token,
			Flag:       "token",
			Short:      't',
			Desc:       "API token to be used throughout client calls",
			Persistent: true,
		},
		{
			DestP:      &flags.Host,
			Flag:       "host",
			Default:    "http://localhost:9999",
			Desc:       "HTTP address of Influx",
			Persistent: true,
		},
	}
	fOpts.mustRegister(cmd)

	if flags.Token == "" {
		// migration credential token
		migrateOldCredential()

		// this is after the flagOpts register b/c we don't want to show the default value
		// in the usage display. This will add it as the config, then if a token flag
		// is provided too, the flag will take precedence.
		flags.Config = getConfigFromDefaultPath()
	}

	cmd.PersistentFlags().BoolVar(&flags.local, "local", false, "Run commands locally against the filesystem")
	cmd.PersistentFlags().BoolVar(&flags.skipVerify, "skip-verify", false, "SkipVerify controls whether a client verifies the server's certificate chain and host name.")

	// Update help description for all commands in command tree
	walk(cmd, func(c *cobra.Command) {
		c.Flags().BoolP("help", "h", false, fmt.Sprintf("Help for the %s command ", c.Name()))
	})

	// completion command goes last, after the walk, so that all
	// commands have every flag listed in the bash|zsh completions.
	cmd.AddCommand(completionCmd(cmd))
	return cmd
}

func influxCmd(opts ...genericCLIOptFn) *cobra.Command {
	builder := newInfluxCmdBuilder(opts...)
	return builder.cmd(
		cmdAuth,
		cmdBackup,
		cmdBucket,
		cmdDelete,
		cmdOrganization,
		cmdPing,
		cmdPkg,
		cmdConfig,
		cmdQuery,
		cmdTranspile,
		cmdREPL,
		cmdSecret,
		cmdSetup,
		cmdTask,
		cmdUser,
		cmdWrite,
	)
}

func fetchSubCommand(parent *cobra.Command, args []string) *cobra.Command {
	var err error
	var cmd *cobra.Command

	// Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155
	if args == nil && filepath.Base(os.Args[0]) != "cobra.test" {
		args = os.Args[1:]
	}

	if parent.TraverseChildren {
		cmd, _, err = parent.Traverse(args)
	} else {
		cmd, _, err = parent.Find(args)
	}
	// return nil if any errs
	if err != nil {
		return nil
	}
	return cmd
}

func seeHelp(c *cobra.Command, args []string) {
	if c = fetchSubCommand(c, args); c == nil {
		return //return here, since cobra already handles the error
	}
	c.Printf("See '%s -h' for help\n", c.CommandPath())
}

func defaultConfigPath() (string, string, error) {
	dir, err := fs.InfluxDir()
	if err != nil {
		return "", "", err
	}
	return filepath.Join(dir, http.DefaultConfigsFile), dir, nil
}

func getConfigFromDefaultPath() config.Config {
	path, _, err := defaultConfigPath()
	if err != nil {
		return config.DefaultConfig
	}
	r, err := os.Open(path)
	if err != nil {
		return config.DefaultConfig
	}
	activated, _ := config.ParseActiveConfig(r)
	return activated
}

func migrateOldCredential() {
	dir, err := fs.InfluxDir()
	if err != nil {
		return // no need for migration
	}
	tokB, err := ioutil.ReadFile(filepath.Join(dir, http.DefaultTokenFile))
	if err != nil {
		return // no need for migration
	}
	err = writeConfigToPath(strings.TrimSpace(string(tokB)), "", filepath.Join(dir, http.DefaultConfigsFile), dir)
	if err != nil {
		return
	}
	// ignore the remove err
	_ = os.Remove(filepath.Join(dir, http.DefaultTokenFile))
}

func writeConfigToPath(tok, org, path, dir string) error {
	p := &config.DefaultConfig
	p.Token = tok
	p.Org = org
	pp := map[string]config.Config{
		"default": *p,
	}

	return config.LocalConfigsSVC{
		Path: path,
		Dir:  dir,
	}.WriteConfigs(pp)
}

func checkSetup(host string, skipVerify bool) error {
	s := &http.SetupService{
		Addr:               host,
		InsecureSkipVerify: skipVerify,
	}

	isOnboarding, err := s.IsOnboarding(context.Background())
	if err != nil {
		return err
	}

	if isOnboarding {
		return fmt.Errorf("the instance at %q has not been setup. Please run `influx setup` before issuing any additional commands", host)
	}

	return nil
}

func checkSetupRunEMiddleware(f *globalFlags) cobraRunEMiddleware {
	return func(fn cobraRunEFn) cobraRunEFn {
		return func(cmd *cobra.Command, args []string) error {
			err := fn(cmd, args)
			if err == nil {
				return nil
			}

			if setupErr := checkSetup(f.Host, f.skipVerify); setupErr != nil && influxdb.EUnauthorized != influxdb.ErrorCode(setupErr) {
				cmd.OutOrStderr().Write([]byte(fmt.Sprintf("Error: %s\n", internal.ErrorFmt(err).Error())))
				return internal.ErrorFmt(setupErr)
			}

			return internal.ErrorFmt(err)
		}
	}
}

// walk calls f for c and all of its children.
func walk(c *cobra.Command, f func(*cobra.Command)) {
	f(c)
	for _, c := range c.Commands() {
		walk(c, f)
	}
}

func newLocalKVService() (*kv.Service, error) {
	boltFile, err := fs.BoltFile()
	if err != nil {
		return nil, err
	}

	store := bolt.NewKVStore(zap.NewNop(), boltFile)
	if err := store.Open(context.Background()); err != nil {
		return nil, err
	}

	return kv.NewService(zap.NewNop(), store), nil
}

type organization struct {
	id, name string
}

func (o *organization) register(cmd *cobra.Command, persistent bool) {
	opts := flagOpts{
		{
			DestP:      &o.id,
			Flag:       "org-id",
			Desc:       "The ID of the organization",
			Persistent: persistent,
		},
		{
			DestP:      &o.name,
			Flag:       "org",
			Short:      'o',
			Desc:       "The name of the organization",
			Persistent: persistent,
		},
	}
	opts.mustRegister(cmd)
}

func (o *organization) getID(orgSVC influxdb.OrganizationService) (influxdb.ID, error) {
	if o.id != "" {
		influxOrgID, err := influxdb.IDFromString(o.id)
		if err != nil {
			return 0, fmt.Errorf("invalid org ID provided: %s", err.Error())
		}
		return *influxOrgID, nil
	} else if o.name != "" {
		org, err := orgSVC.FindOrganization(context.Background(), influxdb.OrganizationFilter{
			Name: &o.name,
		})
		if err != nil {
			return 0, fmt.Errorf("%v", err)
		}
		return org.ID, nil
	}
	return 0, fmt.Errorf("failed to locate an organization id")
}

func (o *organization) validOrgFlags(f *globalFlags) error {
	if o.id == "" && o.name == "" && f != nil {
		o.name = f.Org
	}

	if o.id == "" && o.name == "" {
		return fmt.Errorf("must specify org-id, or org name")
	} else if o.id != "" && o.name != "" {
		return fmt.Errorf("must specify org-id, or org name not both")
	}
	return nil
}

type flagOpts []cli.Opt

func (f flagOpts) mustRegister(cmd *cobra.Command) {
	for i := range f {
		envVar := f[i].Flag
		if e := f[i].EnvVar; e != "" {
			envVar = e
		}

		f[i].Desc = fmt.Sprintf(
			"%s; Maps to env var $INFLUX_%s",
			f[i].Desc,
			strings.ToUpper(strings.Replace(envVar, "-", "_", -1)),
		)
	}
	cli.BindOptions(cmd, f)
}

func setViperOptions() {
	viper.SetEnvPrefix("INFLUX")
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
}

func newBucketService() (influxdb.BucketService, error) {
	if flags.local {
		return newLocalKVService()
	}

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

	return &http.BucketService{
		Client: client,
	}, nil
}
<commit_msg>feat(cmd/write): don't check setup for dry-run executions<commit_after>package main

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/influxdata/influxdb"
	"github.com/influxdata/influxdb/bolt"
	"github.com/influxdata/influxdb/cmd/influx/config"
	"github.com/influxdata/influxdb/cmd/influx/internal"
	"github.com/influxdata/influxdb/http"
	"github.com/influxdata/influxdb/internal/fs"
	"github.com/influxdata/influxdb/kit/cli"
	"github.com/influxdata/influxdb/kv"
	"github.com/influxdata/influxdb/pkg/httpc"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"go.uber.org/zap"
)

const maxTCPConnections = 128

func main() {
	influxCmd := influxCmd()
	if err := influxCmd.Execute(); err != nil {
		seeHelp(influxCmd, nil)
		os.Exit(1)
	}
}

var (
	httpClient *httpc.Client
)

func newHTTPClient() (*httpc.Client, error) {
	if httpClient != nil {
		return httpClient, nil
	}

	c, err := http.NewHTTPClient(flags.Host, flags.Token, flags.skipVerify)
	if err != nil {
		return nil, err
	}

	httpClient = c
	return httpClient, nil
}

type (
	cobraRunEFn func(cmd *cobra.Command, args []string) error

	cobraRunEMiddleware func(fn cobraRunEFn) cobraRunEFn

	genericCLIOptFn func(*genericCLIOpts)
)

type genericCLIOpts struct {
	in   io.Reader
	w    io.Writer
	errW io.Writer

	runEWrapFn cobraRunEMiddleware
}

func (o genericCLIOpts) newCmd(use string, runE func(*cobra.Command, []string) error, useRunEMiddleware bool) *cobra.Command {
	cmd := &cobra.Command{
		Args: cobra.NoArgs,
		Use:  use,
		RunE: runE,
	}

	canWrapRunE := runE != nil && o.runEWrapFn != nil
	if useRunEMiddleware && canWrapRunE {
		cmd.RunE = o.runEWrapFn(runE)
	} else if canWrapRunE {
		cmd.RunE = runE
	}

	cmd.SetOut(o.w)
	cmd.SetIn(o.in)
	cmd.SetErr(o.errW)
	return cmd
}

func (o genericCLIOpts) newTabWriter() *internal.TabWriter {
	return internal.NewTabWriter(o.w)
}

func in(r io.Reader) genericCLIOptFn {
	return func(o *genericCLIOpts) {
		o.in = r
	}
}

func out(w io.Writer) genericCLIOptFn {
	return func(o *genericCLIOpts) {
		o.w = w
	}
}

func err(w io.Writer) genericCLIOptFn {
	return func(o *genericCLIOpts) {
		o.errW = w
	}
}

func runEMiddlware(mw cobraRunEMiddleware) genericCLIOptFn {
	return func(o *genericCLIOpts) {
		o.runEWrapFn = mw
	}
}

type globalFlags struct {
	config.Config
	local      bool
	skipVerify bool
}

var flags globalFlags

type cmdInfluxBuilder struct {
	genericCLIOpts

	once sync.Once
}

func newInfluxCmdBuilder(optFns ...genericCLIOptFn) *cmdInfluxBuilder {
	builder := new(cmdInfluxBuilder)

	opt := genericCLIOpts{
		in:         os.Stdin,
		w:          os.Stdout,
		errW:       os.Stderr,
		runEWrapFn: checkSetupRunEMiddleware(&flags),
	}
	for _, optFn := range optFns {
		optFn(&opt)
	}

	builder.genericCLIOpts = opt
	return builder
}

func (b *cmdInfluxBuilder) cmd(childCmdFns ...func(f *globalFlags, opt genericCLIOpts) *cobra.Command) *cobra.Command {
	b.once.Do(func() {
		// enforce that viper options only ever get set once
		setViperOptions()
	})

	cmd := b.newCmd("influx", nil, false)
	cmd.Short = "Influx Client"
	cmd.SilenceUsage = true

	for _, childCmd := range childCmdFns {
		cmd.AddCommand(childCmd(&flags, b.genericCLIOpts))
	}

	fOpts := flagOpts{
		{
			DestP:      &flags.Token,
			Flag:       "token",
			Short:      't',
			Desc:       "API token to be used throughout client calls",
			Persistent: true,
		},
		{
			DestP:      &flags.Host,
			Flag:       "host",
			Default:    "http://localhost:9999",
			Desc:       "HTTP address of Influx",
			Persistent: true,
		},
	}
	fOpts.mustRegister(cmd)

	if flags.Token == "" {
		// migration credential token
		migrateOldCredential()

		// this is after the flagOpts register b/c we don't want to show the default value
		// in the usage display. This will add it as the config, then if a token flag
		// is provided too, the flag will take precedence.
		flags.Config = getConfigFromDefaultPath()
	}

	cmd.PersistentFlags().BoolVar(&flags.local, "local", false, "Run commands locally against the filesystem")
	cmd.PersistentFlags().BoolVar(&flags.skipVerify, "skip-verify", false, "SkipVerify controls whether a client verifies the server's certificate chain and host name.")

	// Update help description for all commands in command tree
	walk(cmd, func(c *cobra.Command) {
		c.Flags().BoolP("help", "h", false, fmt.Sprintf("Help for the %s command ", c.Name()))
	})

	// completion command goes last, after the walk, so that all
	// commands have every flag listed in the bash|zsh completions.
	cmd.AddCommand(completionCmd(cmd))
	return cmd
}

func influxCmd(opts ...genericCLIOptFn) *cobra.Command {
	builder := newInfluxCmdBuilder(opts...)
	return builder.cmd(
		cmdAuth,
		cmdBackup,
		cmdBucket,
		cmdDelete,
		cmdOrganization,
		cmdPing,
		cmdPkg,
		cmdConfig,
		cmdQuery,
		cmdTranspile,
		cmdREPL,
		cmdSecret,
		cmdSetup,
		cmdTask,
		cmdUser,
		cmdWrite,
	)
}

func fetchSubCommand(parent *cobra.Command, args []string) *cobra.Command {
	var err error
	var cmd *cobra.Command

	// Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155
	if args == nil && filepath.Base(os.Args[0]) != "cobra.test" {
		args = os.Args[1:]
	}

	if parent.TraverseChildren {
		cmd, _, err = parent.Traverse(args)
	} else {
		cmd, _, err = parent.Find(args)
	}
	// return nil if any errs
	if err != nil {
		return nil
	}
	return cmd
}

func seeHelp(c *cobra.Command, args []string) {
	if c = fetchSubCommand(c, args); c == nil {
		return //return here, since cobra already handles the error
	}
	c.Printf("See '%s -h' for help\n", c.CommandPath())
}

func defaultConfigPath() (string, string, error) {
	dir, err := fs.InfluxDir()
	if err != nil {
		return "", "", err
	}
	return filepath.Join(dir, http.DefaultConfigsFile), dir, nil
}

func getConfigFromDefaultPath() config.Config {
	path, _, err := defaultConfigPath()
	if err != nil {
		return config.DefaultConfig
	}
	r, err := os.Open(path)
	if err != nil {
		return config.DefaultConfig
	}
	activated, _ := config.ParseActiveConfig(r)
	return activated
}

func migrateOldCredential() {
	dir, err := fs.InfluxDir()
	if err != nil {
		return // no need for migration
	}
	tokB, err := ioutil.ReadFile(filepath.Join(dir, http.DefaultTokenFile))
	if err != nil {
		return // no need for migration
	}
	err = writeConfigToPath(strings.TrimSpace(string(tokB)), "", filepath.Join(dir, http.DefaultConfigsFile), dir)
	if err != nil {
		return
	}
	// ignore the remove err
	_ = os.Remove(filepath.Join(dir, http.DefaultTokenFile))
}

func writeConfigToPath(tok, org, path, dir string) error {
	p := &config.DefaultConfig
	p.Token = tok
	p.Org = org
	pp := map[string]config.Config{
		"default": *p,
	}

	return config.LocalConfigsSVC{
		Path: path,
		Dir:  dir,
	}.WriteConfigs(pp)
}

func checkSetup(host string, skipVerify bool) error {
	if host == "-" {
		// dry run executed
		return nil
	}
	s := &http.SetupService{
		Addr:               host,
		InsecureSkipVerify: skipVerify,
	}

	isOnboarding, err := s.IsOnboarding(context.Background())
	if err != nil {
		return err
	}

	if isOnboarding {
		return fmt.Errorf("the instance at %q has not been setup. Please run `influx setup` before issuing any additional commands", host)
	}

	return nil
}

func checkSetupRunEMiddleware(f *globalFlags) cobraRunEMiddleware {
	return func(fn cobraRunEFn) cobraRunEFn {
		return func(cmd *cobra.Command, args []string) error {
			err := fn(cmd, args)
			if err == nil {
				return nil
			}

			if setupErr := checkSetup(f.Host, f.skipVerify); setupErr != nil && influxdb.EUnauthorized != influxdb.ErrorCode(setupErr) {
				cmd.OutOrStderr().Write([]byte(fmt.Sprintf("Error: %s\n", internal.ErrorFmt(err).Error())))
				return internal.ErrorFmt(setupErr)
			}

			return internal.ErrorFmt(err)
		}
	}
}

// walk calls f for c and all of its children.
func walk(c *cobra.Command, f func(*cobra.Command)) {
	f(c)
	for _, c := range c.Commands() {
		walk(c, f)
	}
}

func newLocalKVService() (*kv.Service, error) {
	boltFile, err := fs.BoltFile()
	if err != nil {
		return nil, err
	}

	store := bolt.NewKVStore(zap.NewNop(), boltFile)
	if err := store.Open(context.Background()); err != nil {
		return nil, err
	}

	return kv.NewService(zap.NewNop(), store), nil
}

type organization struct {
	id, name string
}

func (o *organization) register(cmd *cobra.Command, persistent bool) {
	opts := flagOpts{
		{
			DestP:      &o.id,
			Flag:       "org-id",
			Desc:       "The ID of the organization",
			Persistent: persistent,
		},
		{
			DestP:      &o.name,
			Flag:       "org",
			Short:      'o',
			Desc:       "The name of the organization",
			Persistent: persistent,
		},
	}
	opts.mustRegister(cmd)
}

func (o *organization) getID(orgSVC influxdb.OrganizationService) (influxdb.ID, error) {
	if o.id != "" {
		influxOrgID, err := influxdb.IDFromString(o.id)
		if err != nil {
			return 0, fmt.Errorf("invalid org ID provided: %s", err.Error())
		}
		return *influxOrgID, nil
	} else if o.name != "" {
		org, err := orgSVC.FindOrganization(context.Background(), influxdb.OrganizationFilter{
			Name: &o.name,
		})
		if err != nil {
			return 0, fmt.Errorf("%v", err)
		}
		return org.ID, nil
	}
	return 0, fmt.Errorf("failed to locate an organization id")
}

func (o *organization) validOrgFlags(f *globalFlags) error {
	if o.id == "" && o.name == "" && f != nil {
		o.name = f.Org
	}

	if o.id == "" && o.name == "" {
		return fmt.Errorf("must specify org-id, or org name")
	} else if o.id != "" && o.name != "" {
		return fmt.Errorf("must specify org-id, or org name not both")
	}
	return nil
}

type flagOpts []cli.Opt

func (f flagOpts) mustRegister(cmd *cobra.Command) {
	for i := range f {
		envVar := f[i].Flag
		if e := f[i].EnvVar; e != "" {
			envVar = e
		}

		f[i].Desc = fmt.Sprintf(
			"%s; Maps to env var $INFLUX_%s",
			f[i].Desc,
			strings.ToUpper(strings.Replace(envVar, "-", "_", -1)),
		)
	}
	cli.BindOptions(cmd, f)
}

func setViperOptions() {
	viper.SetEnvPrefix("INFLUX")
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
}

func newBucketService() (influxdb.BucketService, error) {
	if flags.local {
		return newLocalKVService()
	}

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

	return &http.BucketService{
		Client: client,
	}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"os/signal"
	"path/filepath"
	"strings"

	"github.com/uli-go/xz/lzma"
	"github.com/uli-go/xz/xlog"
)

type packer interface {
	outputPaths(path string) (outputPath, tmpPath string, err error)
	pack(w io.Writer, r io.Reader, preset int) (n int64, err error)
}

const lzmaSuffix = ".lzma"

// parameters converts the lzmago executable flags to lzma parameters.
//
// I cannot use the preset config from the Tukaani project directly,
// because I don't have two algorithm modes and can't support parameters
// like nice_len or depth. So at this point in time I stay with the
// dictionary sizes the default combination of (LC,LP,LB) = (3,0,2).
// The default preset is 6.
// Following list provides exponents of two for the dictionary sizes:
// 18, 20, 21, 22, 22, 23, 23, 24, 25, 26.
func parameters(preset int) lzma.Parameters {
	dictSizeExps := []uint{18, 20, 21, 22, 22, 23, 23, 24, 25, 26}
	dictSize := int64(1) << dictSizeExps[preset]
	p := lzma.Parameters{
		LC:           3,
		LP:           0,
		PB:           2,
		DictSize:     dictSize,
		EOS:          true,
		ExtraBufSize: 16 * 1024,
	}
	return p
}

type lzmaPacker struct{}

func (p lzmaPacker) outputPaths(path string) (out, tmp string, err error) {
	if path == "-" {
		return "-", "-", nil
	}
	if path == "" {
		err = errors.New("path is empty")
		return
	}
	if strings.HasSuffix(path, lzmaSuffix) {
		err = fmt.Errorf("path %s has suffix %s -- ignored",
			path, lzmaSuffix)
		return
	}
	out = path + lzmaSuffix
	tmp = out + ".pack"
	return
}

func (p lzmaPacker) pack(w io.Writer, r io.Reader, preset int) (n int64, err error) {
	if w == nil {
		panic("writer w is nil")
	}
	if r == nil {
		panic("reader r is nil")
	}
	params := parameters(preset)
	bw := bufio.NewWriter(w)
	lw, err := lzma.NewWriterParams(bw, params)
	if err != nil {
		return
	}
	n, err = io.Copy(lw, r)
	if err != nil {
		return
	}
	if err = lw.Close(); err != nil {
		return
	}
	err = bw.Flush()
	return
}

type lzmaUnpacker struct{}

func (u lzmaUnpacker) outputPaths(path string) (out, tmp string, err error) {
	if path == "-" {
		return "-", "-", nil
	}
	if !strings.HasSuffix(path, lzmaSuffix) {
		err = fmt.Errorf("path %s has no suffix %s",
			path, lzmaSuffix)
		return
	}
	base := filepath.Base(path)
	if base == lzmaSuffix {
		err = fmt.Errorf(
			"path %s has only suffix %s as filename",
			path, lzmaSuffix)
		return
	}
	out = path[:len(path)-len(lzmaSuffix)]
	tmp = out + ".unpack"
	return
}

func (u lzmaUnpacker) pack(w io.Writer, r io.Reader, preset int) (n int64, err error) {
	if w == nil {
		panic("writer w is nil")
	}
	if r == nil {
		panic("reader r is nil")
	}
	// pack actually unpacks
	br := bufio.NewReader(r)
	lr, err := lzma.NewReader(br)
	if err != nil {
		return
	}
	n, err = io.Copy(w, lr)
	return
}

func signalHandler(tmpPath string) chan<- struct{} {
	quit := make(chan struct{})
	sigch := make(chan os.Signal, 1)
	signal.Notify(sigch, os.Interrupt)
	go func() {
		select {
		case <-quit:
			signal.Stop(sigch)
			return
		case <-sigch:
			if tmpPath != "-" {
				os.Remove(tmpPath)
			}
			os.Exit(7)
		}
	}()
	return quit
}

func packFile(pck packer, path, tmpPath string, opts *options) error {
	var err error

	// open reader
	var r *os.File
	if path == "-" {
		r = os.Stdin
	} else {
		fi, err := os.Lstat(path)
		if err != nil {
			return err
		}
		if !fi.Mode().IsRegular() {
			return fmt.Errorf("%s is not a regular file", path)
		}
		r, err = os.Open(path)
		if err != nil {
			return err
		}
		fi, err = r.Stat()
		if err != nil {
			r.Close()
			return err
		}
		if !fi.Mode().IsRegular() {
			r.Close()
			return fmt.Errorf("%s is not a regular file", path)
		}
	}
	defer func() {
		if err != nil {
			r.Close()
		} else {
			err = r.Close()
		}
	}()

	// open writer
	var w *os.File
	if tmpPath == "-" {
		w = os.Stdout
	} else {
		if opts.force {
			os.Remove(tmpPath)
		}
		w, err = os.OpenFile(tmpPath,
			os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
		if err != nil {
			return err
		}
		defer func() {
			if err != nil {
				w.Close()
			} else {
				err = w.Close()
			}
		}()
		fi, err := w.Stat()
		if err != nil {
			return err
		}
		if !fi.Mode().IsRegular() {
			return fmt.Errorf("%s is not a regular file", tmpPath)
		}
	}

	_, err = pck.pack(w, r, opts.preset)
	return err
}

func processFile(path string, opts *options) {
	var pck packer
	if opts.decompress {
		pck = lzmaUnpacker{}
	} else {
		pck = lzmaPacker{}
	}
	outputPath, tmpPath, err := pck.outputPaths(path)
	if err != nil {
		xlog.Warn(err)
		return
	}
	if opts.stdout {
		outputPath, tmpPath = "-", "-"
	}
	if outputPath != "-" {
		_, err = os.Lstat(outputPath)
		if err == nil && !opts.force {
			xlog.Warnf("file %s exists", outputPath)
			return
		}
	}
	defer func(tmp string) {
		if tmp != "-" {
			os.Remove(tmp)
		}
	}(tmpPath)
	quit := signalHandler(tmpPath)
	defer close(quit)

	if err = packFile(pck, path, tmpPath, opts); err != nil {
		xlog.Warn(err)
		return
	}
	if tmpPath != "-" && outputPath != "-" {
		if err = os.Rename(tmpPath, outputPath); err != nil {
			xlog.Warn(err)
			return
		}
	}
	if !opts.keep && !opts.stdout && path != "-" {
		if err = os.Remove(path); err != nil {
			xlog.Warn(err)
			return
		}
	}
}
<commit_msg>lzmago: minor improvement in processFile<commit_after>package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"os/signal"
	"path/filepath"
	"strings"

	"github.com/uli-go/xz/lzma"
	"github.com/uli-go/xz/xlog"
)

type packer interface {
	outputPaths(path string) (outputPath, tmpPath string, err error)
	pack(w io.Writer, r io.Reader, preset int) (n int64, err error)
}

const lzmaSuffix = ".lzma"

// parameters converts the lzmago executable flags to lzma parameters.
//
// I cannot use the preset config from the Tukaani project directly,
// because I don't have two algorithm modes and can't support parameters
// like nice_len or depth. So at this point in time I stay with the
// dictionary sizes the default combination of (LC,LP,LB) = (3,0,2).
// The default preset is 6.
// Following list provides exponents of two for the dictionary sizes:
// 18, 20, 21, 22, 22, 23, 23, 24, 25, 26.
func parameters(preset int) lzma.Parameters {
	dictSizeExps := []uint{18, 20, 21, 22, 22, 23, 23, 24, 25, 26}
	dictSize := int64(1) << dictSizeExps[preset]
	p := lzma.Parameters{
		LC:           3,
		LP:           0,
		PB:           2,
		DictSize:     dictSize,
		EOS:          true,
		ExtraBufSize: 16 * 1024,
	}
	return p
}

type lzmaPacker struct{}

func (p lzmaPacker) outputPaths(path string) (out, tmp string, err error) {
	if path == "-" {
		return "-", "-", nil
	}
	if path == "" {
		err = errors.New("path is empty")
		return
	}
	if strings.HasSuffix(path, lzmaSuffix) {
		err = fmt.Errorf("path %s has suffix %s -- ignored",
			path, lzmaSuffix)
		return
	}
	out = path + lzmaSuffix
	tmp = out + ".pack"
	return
}

func (p lzmaPacker) pack(w io.Writer, r io.Reader, preset int) (n int64, err error) {
	if w == nil {
		panic("writer w is nil")
	}
	if r == nil {
		panic("reader r is nil")
	}
	params := parameters(preset)
	bw := bufio.NewWriter(w)
	lw, err := lzma.NewWriterParams(bw, params)
	if err != nil {
		return
	}
	n, err = io.Copy(lw, r)
	if err != nil {
		return
	}
	if err = lw.Close(); err != nil {
		return
	}
	err = bw.Flush()
	return
}

type lzmaUnpacker struct{}

func (u lzmaUnpacker) outputPaths(path string) (out, tmp string, err error) {
	if path == "-" {
		return "-", "-", nil
	}
	if !strings.HasSuffix(path, lzmaSuffix) {
		err = fmt.Errorf("path %s has no suffix %s",
			path, lzmaSuffix)
		return
	}
	base := filepath.Base(path)
	if base == lzmaSuffix {
		err = fmt.Errorf(
			"path %s has only suffix %s as filename",
			path, lzmaSuffix)
		return
	}
	out = path[:len(path)-len(lzmaSuffix)]
	tmp = out + ".unpack"
	return
}

func (u lzmaUnpacker) pack(w io.Writer, r io.Reader, preset int) (n int64, err error) {
	if w == nil {
		panic("writer w is nil")
	}
	if r == nil {
		panic("reader r is nil")
	}
	// pack actually unpacks
	br := bufio.NewReader(r)
	lr, err := lzma.NewReader(br)
	if err != nil {
		return
	}
	n, err = io.Copy(w, lr)
	return
}

func signalHandler(tmpPath string) chan<- struct{} {
	quit := make(chan struct{})
	sigch := make(chan os.Signal, 1)
	signal.Notify(sigch, os.Interrupt)
	go func() {
		select {
		case <-quit:
			signal.Stop(sigch)
			return
		case <-sigch:
			if tmpPath != "-" {
				os.Remove(tmpPath)
			}
			os.Exit(7)
		}
	}()
	return quit
}

func packFile(pck packer, path, tmpPath string, opts *options) error {
	var err error

	// open reader
	var r *os.File
	if path == "-" {
		r = os.Stdin
	} else {
		fi, err := os.Lstat(path)
		if err != nil {
			return err
		}
		if !fi.Mode().IsRegular() {
			return fmt.Errorf("%s is not a regular file", path)
		}
		r, err = os.Open(path)
		if err != nil {
			return err
		}
		fi, err = r.Stat()
		if err != nil {
			r.Close()
			return err
		}
		if !fi.Mode().IsRegular() {
			r.Close()
			return fmt.Errorf("%s is not a regular file", path)
		}
	}
	defer func() {
		if err != nil {
			r.Close()
		} else {
			err = r.Close()
		}
	}()

	// open writer
	var w *os.File
	if tmpPath == "-" {
		w = os.Stdout
	} else {
		if opts.force {
			os.Remove(tmpPath)
		}
		w, err = os.OpenFile(tmpPath,
			os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
		if err != nil {
			return err
		}
		defer func() {
			if err != nil {
				w.Close()
			} else {
				err = w.Close()
			}
		}()
		fi, err := w.Stat()
		if err != nil {
			return err
		}
		if !fi.Mode().IsRegular() {
			return fmt.Errorf("%s is not a regular file", tmpPath)
		}
	}

	_, err = pck.pack(w, r, opts.preset)
	return err
}

func processFile(path string, opts *options) {
	var pck packer
	if opts.decompress {
		pck = lzmaUnpacker{}
	} else {
		pck = lzmaPacker{}
	}
	outputPath, tmpPath, err := pck.outputPaths(path)
	if err != nil {
		xlog.Warn(err)
		return
	}
	if opts.stdout {
		outputPath, tmpPath = "-", "-"
	}
	if outputPath != "-" {
		_, err = os.Lstat(outputPath)
		if err == nil && !opts.force {
			xlog.Warnf("file %s exists", outputPath)
			return
		}
	}
	defer func() {
		if tmpPath != "-" {
			os.Remove(tmp)
		}
	}()
	quit := signalHandler(tmpPath)
	defer close(quit)

	if err = packFile(pck, path, tmpPath, opts); err != nil {
		xlog.Warn(err)
		return
	}
	if tmpPath != "-" && outputPath != "-" {
		if err = os.Rename(tmpPath, outputPath); err != nil {
			xlog.Warn(err)
			return
		}
	}
	if !opts.keep && !opts.stdout && path != "-" {
		if err = os.Remove(path); err != nil {
			xlog.Warn(err)
			return
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"sort"

	"github.com/ecc1/medtronic"
	"github.com/ecc1/radio"
)

const (
	startFreq = uint32(916000000)
	endFreq   = uint32(917000000)
	precision = uint32(10000)
)

func main() {
	pump := medtronic.Open()
	if pump.Error() != nil {
		log.Fatal(pump.Error())
	}
	defer pump.Close()
	f := searchFrequencies(pump)
	showResults(f)
	fmt.Println(radio.MegaHertz(f))
}

// Use ternary search to find frequency with maximum RSSI.
func searchFrequencies(pump *medtronic.Pump) uint32 {
	pump.SetRetries(1)
	lower := startFreq
	upper := endFreq
	for {
		delta := upper - lower
		if delta < precision {
			return (lower + upper) / 2
		}
		delta /= 3
		lowerThird := lower + delta
		r1 := tryFrequency(pump, lowerThird)
		upperThird := upper - delta
		r2 := tryFrequency(pump, upperThird)
		if r1 < r2 {
			lower = lowerThird
		} else {
			upper = upperThird
		}
	}
}

// Result represents the RSSI at a given frequency.
type Result struct {
	frequency uint32
	rssi      int
}

// Results implements sort.Interface based on frequency.
type Results []Result

func (r Results) Len() int           { return len(r) }
func (r Results) Swap(i, j int)      { r[i], r[j] = r[j], r[i] }
func (r Results) Less(i, j int) bool { return r[i].frequency < r[j].frequency }

var results Results

func tryFrequency(pump *medtronic.Pump, freq uint32) int {
	const sampleSize = 2
	pump.Radio.SetFrequency(freq)
	log.Printf("frequency set to %s", radio.MegaHertz(freq))
	rssi := -128
	count := 0
	sum := 0
	for i := 0; i < sampleSize; i++ {
		pump.Model()
		if pump.Error() != nil {
			pump.SetError(nil)
			continue
		}
		sum += pump.RSSI()
		count++
	}
	if count != 0 {
		rssi = (sum + count/2) / count
	}
	results = append(results, Result{frequency: freq, rssi: rssi})
	return rssi
}

func showResults(winner uint32) {
	sort.Sort(results)
	for _, r := range results {
		fmt.Printf("%s  %4d ", radio.MegaHertz(r.frequency), r.rssi)
		n := r.rssi + 128
		for i := 0; i < n; i++ {
			fmt.Print("━")
		}
		if r.frequency == winner {
			fmt.Print(" ⏺")
		}
		fmt.Printf("\n")
	}
	fmt.Printf("\n")
}
<commit_msg>Use linear search and add single-frequency argument<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"sort"

	"github.com/ecc1/medtronic"
	"github.com/ecc1/radio"
)

const (
	startFreq = uint32(916000000)
	endFreq   = uint32(917000000)
	deltaHz   = uint32(100000)
)

func main() {
	if len(os.Args) > 2 {
		log.Fatalf("Usage: %s [frequency]", os.Args[0])
	}
	pump := medtronic.Open()
	if pump.Error() != nil {
		log.Fatal(pump.Error())
	}
	defer pump.Close()
	pump.Wakeup()
	switch len(os.Args) {
	case 1:
		f := searchFrequencies(pump)
		showResults(f)
		fmt.Println(radio.MegaHertz(f))
	case 2:
		f, err := medtronic.ParseFrequency(os.Args[1])
		if err != nil {
			log.Fatal(err)
		}
		rssi := tryFrequency(pump, f)
		fmt.Printf("%s  %4d\n", radio.MegaHertz(f), rssi)
	}
}

// Find frequency with maximum RSSI.
func searchFrequencies(pump *medtronic.Pump) uint32 {
	pump.SetRetries(1)
	maxRSSI := -128
	bestFreq := startFreq
	for f := startFreq; f <= endFreq; f += deltaHz {
		rssi := tryFrequency(pump, f)
		if rssi > maxRSSI {
			maxRSSI = rssi
			bestFreq = f
		}
	}
	return bestFreq
}

// Result represents the RSSI at a given frequency.
type Result struct {
	frequency uint32
	rssi      int
}

// Results implements sort.Interface based on frequency.
type Results []Result

func (r Results) Len() int           { return len(r) }
func (r Results) Swap(i, j int)      { r[i], r[j] = r[j], r[i] }
func (r Results) Less(i, j int) bool { return r[i].frequency < r[j].frequency }

var results Results

func tryFrequency(pump *medtronic.Pump, freq uint32) int {
	const sampleSize = 2
	pump.Radio.SetFrequency(freq)
	log.Printf("frequency set to %s", radio.MegaHertz(freq))
	rssi := -128
	count := 0
	sum := 0
	for i := 0; i < sampleSize; i++ {
		pump.Model()
		if pump.Error() != nil {
			pump.SetError(nil)
			continue
		}
		sum += pump.RSSI()
		count++
	}
	if count != 0 {
		rssi = (sum + count/2) / count
	}
	results = append(results, Result{frequency: freq, rssi: rssi})
	return rssi
}

func showResults(winner uint32) {
	sort.Sort(results)
	for _, r := range results {
		fmt.Printf("%s  %4d ", radio.MegaHertz(r.frequency), r.rssi)
		n := r.rssi + 128
		for i := 0; i < n; i++ {
			fmt.Print("━")
		}
		if r.frequency == winner {
			fmt.Print(" ⏺")
		}
		fmt.Printf("\n")
	}
	fmt.Printf("\n")
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package main

import (
	"flag"
	"fmt"
	"os"
	"time"

	"github.com/golang/glog"
	"github.com/spf13/pflag"

	apiv1 "k8s.io/api/core/v1"

	"k8s.io/ingress-nginx/internal/ingress/annotations/class"
	"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
	"k8s.io/ingress-nginx/internal/ingress/controller"
	ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
	ing_net "k8s.io/ingress-nginx/internal/net"
)

func parseFlags() (bool, *controller.Configuration, error) {
	var (
		flags = pflag.NewFlagSet("", pflag.ExitOnError)

		apiserverHost = flags.String("apiserver-host", "", "The address of the Kubernetes Apiserver "+
			"to connect to in the format of protocol://address:port, e.g., "+
			"http://localhost:8080. If not specified, the assumption is that the binary runs inside a "+
			"Kubernetes cluster and local discovery is attempted.")
		kubeConfigFile = flags.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information.")

		defaultSvc = flags.String("default-backend-service", "",
			`Service used to serve a 404 page for the default backend. Takes the form
		namespace/name. The controller uses the first node port of this Service for
		the default backend.`)

		ingressClass = flags.String("ingress-class", "",
			`Name of the ingress class to route through this controller.`)

		configMap = flags.String("configmap", "",
			`Name of the ConfigMap that contains the custom configuration to use`)

		publishSvc = flags.String("publish-service", "",
			`Service fronting the ingress controllers. Takes the form namespace/name.
		The controller will set the endpoint records on the ingress objects to reflect those on the service.`)

		tcpConfigMapName = flags.String("tcp-services-configmap", "",
			`Name of the ConfigMap that contains the definition of the TCP services to expose.
		The key in the map indicates the external port to be used. The value is the name of the
		service with the format namespace/serviceName and the port of the service could be a
		number of the name of the port.
		The ports 80 and 443 are not allowed as external ports. This ports are reserved for the backend`)

		udpConfigMapName = flags.String("udp-services-configmap", "",
			`Name of the ConfigMap that contains the definition of the UDP services to expose.
		The key in the map indicates the external port to be used. The value is the name of the
		service with the format namespace/serviceName and the port of the service could be a
		number of the name of the port.`)

		resyncPeriod = flags.Duration("sync-period", 600*time.Second,
			`Relist and confirm cloud resources this often. Default is 10 minutes`)

		watchNamespace = flags.String("watch-namespace", apiv1.NamespaceAll,
			`Namespace to watch for Ingress. Default is to watch all namespaces`)

		profiling = flags.Bool("profiling", true, `Enable profiling via web interface host:port/debug/pprof/`)

		defSSLCertificate = flags.String("default-ssl-certificate", "", `Name of the secret
		that contains a SSL certificate to be used as default for a HTTPS catch-all server.
		Takes the form <namespace>/<secret name>.`)

		defHealthzURL = flags.String("health-check-path", "/healthz", `Defines
		the URL to be used as health check inside in the default server in NGINX.`)

		updateStatus = flags.Bool("update-status", true, `Indicates if the
		ingress controller should update the Ingress status IP/hostname. Default is true`)

		electionID = flags.String("election-id", "ingress-controller-leader", `Election id to use for status update.`)

		forceIsolation = flags.Bool("force-namespace-isolation", false,
			`Force namespace isolation. This flag is required to avoid the reference of secrets or
		configmaps located in a different namespace than the specified in the flag --watch-namespace.`)

		disableNodeList = flags.Bool("disable-node-list", false,
			`Disable querying nodes. If --force-namespace-isolation is true, this should also be set. (DEPRECATED)`)

		updateStatusOnShutdown = flags.Bool("update-status-on-shutdown", true, `Indicates if the
		ingress controller should update the Ingress status IP/hostname when the controller
		is being stopped. Default is true`)

		sortBackends = flags.Bool("sort-backends", false,
			`Defines if backends and it's endpoints should be sorted`)

		useNodeInternalIP = flags.Bool("report-node-internal-ip-address", false,
			`Defines if the nodes IP address to be returned in the ingress status should be the internal instead of the external IP address`)

		showVersion = flags.Bool("version", false,
			`Shows release information about the NGINX Ingress controller`)

		enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false, `Enable SSL passthrough feature. Default is disabled`)

		httpPort      = flags.Int("http-port", 80, `Indicates the port to use for HTTP traffic`)
		httpsPort     = flags.Int("https-port", 443, `Indicates the port to use for HTTPS traffic`)
		statusPort    = flags.Int("status-port", 18080, `Indicates the TCP port to use for exposing the nginx status page`)
		sslProxyPort  = flags.Int("ssl-passtrough-proxy-port", 442, `Default port to use internally for SSL when SSL Passthgough is enabled`)
		defServerPort = flags.Int("default-server-port", 8181, `Default port to use for exposing the default server (catch all)`)
		healthzPort   = flags.Int("healthz-port", 10254, "port for healthz endpoint.")

		annotationsPrefix = flags.String("annotations-prefix", "nginx.ingress.kubernetes.io", `Prefix of the ingress annotations.`)

		enableSSLChainCompletion = flags.Bool("enable-ssl-chain-completion", true,
			`Defines if the nginx ingress controller should check the secrets for missing intermediate CA certificates.
		If the certificate contain issues chain issues is not possible to enable OCSP.
		Default is true.`)

		syncRateLimit = flags.Float32("sync-rate-limit", 0.3,
			`Define the sync frequency upper limit`)
	)

	flag.Set("logtostderr", "true")

	flags.AddGoFlagSet(flag.CommandLine)
	flags.Parse(os.Args)
	flag.Set("logtostderr", "true")

	// Workaround for this issue:
	// https://github.com/kubernetes/kubernetes/issues/17162
	flag.CommandLine.Parse([]string{})

	if *showVersion {
		return true, nil, nil
	}

	if *defaultSvc == "" {
		return false, nil, fmt.Errorf("Please specify --default-backend-service")
	}

	if *ingressClass != "" {
		glog.Infof("Watching for ingress class: %s", *ingressClass)

		if *ingressClass != class.DefaultClass {
			glog.Warningf("only Ingress with class \"%v\" will be processed by this ingress controller", *ingressClass)
		}

		class.IngressClass = *ingressClass
	}

	parser.AnnotationsPrefix = *annotationsPrefix

	// check port collisions
	if !ing_net.IsPortAvailable(*httpPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --http-port", *httpPort)
	}

	if !ing_net.IsPortAvailable(*httpsPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --https-port", *httpsPort)
	}

	if !ing_net.IsPortAvailable(*statusPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --status-port", *statusPort)
	}

	if !ing_net.IsPortAvailable(*defServerPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --default-server-port", *defServerPort)
	}

	if *enableSSLPassthrough && !ing_net.IsPortAvailable(*sslProxyPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --ssl-passtrough-proxy-port", *sslProxyPort)
	}

	// TODO: remove disableNodeList flag
	if *disableNodeList {
		glog.Warningf("%s is DEPRECATED and will be removed in a future version.", disableNodeList)
	}

	if !*enableSSLChainCompletion {
		glog.Warningf("Check of SSL certificate chain is disabled (--enable-ssl-chain-completion=false)")
	}

	config := &controller.Configuration{
		APIServerHost:            *apiserverHost,
		KubeConfigFile:           *kubeConfigFile,
		UpdateStatus:             *updateStatus,
		ElectionID:               *electionID,
		EnableProfiling:          *profiling,
		EnableSSLPassthrough:     *enableSSLPassthrough,
		EnableSSLChainCompletion: *enableSSLChainCompletion,
		ResyncPeriod:             *resyncPeriod,
		DefaultService:           *defaultSvc,
		Namespace:                *watchNamespace,
		ConfigMapName:            *configMap,
		TCPConfigMapName:         *tcpConfigMapName,
		UDPConfigMapName:         *udpConfigMapName,
		DefaultSSLCertificate:    *defSSLCertificate,
		DefaultHealthzURL:        *defHealthzURL,
		PublishService:           *publishSvc,
		ForceNamespaceIsolation:  *forceIsolation,
		UpdateStatusOnShutdown:   *updateStatusOnShutdown,
		SortBackends:             *sortBackends,
		UseNodeInternalIP:        *useNodeInternalIP,
		SyncRateLimit:            *syncRateLimit,
		ListenPorts: &ngx_config.ListenPorts{
			Default:  *defServerPort,
			Health:   *healthzPort,
			HTTP:     *httpPort,
			HTTPS:    *httpsPort,
			SSLProxy: *sslProxyPort,
			Status:   *statusPort,
		},
	}

	return false, config, nil
}
<commit_msg>remove duplicated code<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package main

import (
	"flag"
	"fmt"
	"os"
	"time"

	"github.com/golang/glog"
	"github.com/spf13/pflag"

	apiv1 "k8s.io/api/core/v1"

	"k8s.io/ingress-nginx/internal/ingress/annotations/class"
	"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
	"k8s.io/ingress-nginx/internal/ingress/controller"
	ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
	ing_net "k8s.io/ingress-nginx/internal/net"
)

func parseFlags() (bool, *controller.Configuration, error) {
	var (
		flags = pflag.NewFlagSet("", pflag.ExitOnError)

		apiserverHost = flags.String("apiserver-host", "", "The address of the Kubernetes Apiserver "+
			"to connect to in the format of protocol://address:port, e.g., "+
			"http://localhost:8080. If not specified, the assumption is that the binary runs inside a "+
			"Kubernetes cluster and local discovery is attempted.")
		kubeConfigFile = flags.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information.")

		defaultSvc = flags.String("default-backend-service", "",
			`Service used to serve a 404 page for the default backend. Takes the form
		namespace/name. The controller uses the first node port of this Service for
		the default backend.`)

		ingressClass = flags.String("ingress-class", "",
			`Name of the ingress class to route through this controller.`)

		configMap = flags.String("configmap", "",
			`Name of the ConfigMap that contains the custom configuration to use`)

		publishSvc = flags.String("publish-service", "",
			`Service fronting the ingress controllers. Takes the form namespace/name.
		The controller will set the endpoint records on the ingress objects to reflect those on the service.`)

		tcpConfigMapName = flags.String("tcp-services-configmap", "",
			`Name of the ConfigMap that contains the definition of the TCP services to expose.
		The key in the map indicates the external port to be used. The value is the name of the
		service with the format namespace/serviceName and the port of the service could be a
		number of the name of the port.
		The ports 80 and 443 are not allowed as external ports. This ports are reserved for the backend`)

		udpConfigMapName = flags.String("udp-services-configmap", "",
			`Name of the ConfigMap that contains the definition of the UDP services to expose.
		The key in the map indicates the external port to be used. The value is the name of the
		service with the format namespace/serviceName and the port of the service could be a
		number of the name of the port.`)

		resyncPeriod = flags.Duration("sync-period", 600*time.Second,
			`Relist and confirm cloud resources this often. Default is 10 minutes`)

		watchNamespace = flags.String("watch-namespace", apiv1.NamespaceAll,
			`Namespace to watch for Ingress. Default is to watch all namespaces`)

		profiling = flags.Bool("profiling", true, `Enable profiling via web interface host:port/debug/pprof/`)

		defSSLCertificate = flags.String("default-ssl-certificate", "", `Name of the secret
		that contains a SSL certificate to be used as default for a HTTPS catch-all server.
		Takes the form <namespace>/<secret name>.`)

		defHealthzURL = flags.String("health-check-path", "/healthz", `Defines
		the URL to be used as health check inside in the default server in NGINX.`)

		updateStatus = flags.Bool("update-status", true, `Indicates if the
		ingress controller should update the Ingress status IP/hostname. Default is true`)

		electionID = flags.String("election-id", "ingress-controller-leader", `Election id to use for status update.`)

		forceIsolation = flags.Bool("force-namespace-isolation", false,
			`Force namespace isolation. This flag is required to avoid the reference of secrets or
		configmaps located in a different namespace than the specified in the flag --watch-namespace.`)

		_ = flags.Bool("disable-node-list", false,
			`Disable querying nodes. If --force-namespace-isolation is true, this should also be set. (DEPRECATED)`)

		updateStatusOnShutdown = flags.Bool("update-status-on-shutdown", true, `Indicates if the
		ingress controller should update the Ingress status IP/hostname when the controller
		is being stopped. Default is true`)

		sortBackends = flags.Bool("sort-backends", false,
			`Defines if backends and it's endpoints should be sorted`)

		useNodeInternalIP = flags.Bool("report-node-internal-ip-address", false,
			`Defines if the nodes IP address to be returned in the ingress status should be the internal instead of the external IP address`)

		showVersion = flags.Bool("version", false,
			`Shows release information about the NGINX Ingress controller`)

		enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false, `Enable SSL passthrough feature. Default is disabled`)

		httpPort      = flags.Int("http-port", 80, `Indicates the port to use for HTTP traffic`)
		httpsPort     = flags.Int("https-port", 443, `Indicates the port to use for HTTPS traffic`)
		statusPort    = flags.Int("status-port", 18080, `Indicates the TCP port to use for exposing the nginx status page`)
		sslProxyPort  = flags.Int("ssl-passtrough-proxy-port", 442, `Default port to use internally for SSL when SSL Passthgough is enabled`)
		defServerPort = flags.Int("default-server-port", 8181, `Default port to use for exposing the default server (catch all)`)
		healthzPort   = flags.Int("healthz-port", 10254, "port for healthz endpoint.")

		annotationsPrefix = flags.String("annotations-prefix", "nginx.ingress.kubernetes.io", `Prefix of the ingress annotations.`)

		enableSSLChainCompletion = flags.Bool("enable-ssl-chain-completion", true,
			`Defines if the nginx ingress controller should check the secrets for missing intermediate CA certificates.
		If the certificate contain issues chain issues is not possible to enable OCSP.
		Default is true.`)

		syncRateLimit = flags.Float32("sync-rate-limit", 0.3,
			`Define the sync frequency upper limit`)
	)

	flags.MarkDeprecated("disable-node-list", "This flag is currently no-op and will be deleted.")

	flag.Set("logtostderr", "true")

	flags.AddGoFlagSet(flag.CommandLine)
	flags.Parse(os.Args)

	// Workaround for this issue:
	// https://github.com/kubernetes/kubernetes/issues/17162
	flag.CommandLine.Parse([]string{})

	pflag.VisitAll(func(flag *pflag.Flag) {
		glog.V(2).Infof("FLAG: --%s=%q", flag.Name, flag.Value)
	})

	if *showVersion {
		return true, nil, nil
	}

	if *defaultSvc == "" {
		return false, nil, fmt.Errorf("Please specify --default-backend-service")
	}

	if *ingressClass != "" {
		glog.Infof("Watching for ingress class: %s", *ingressClass)

		if *ingressClass != class.DefaultClass {
			glog.Warningf("only Ingress with class \"%v\" will be processed by this ingress controller", *ingressClass)
		}

		class.IngressClass = *ingressClass
	}

	parser.AnnotationsPrefix = *annotationsPrefix

	// check port collisions
	if !ing_net.IsPortAvailable(*httpPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --http-port", *httpPort)
	}

	if !ing_net.IsPortAvailable(*httpsPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --https-port", *httpsPort)
	}

	if !ing_net.IsPortAvailable(*statusPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --status-port", *statusPort)
	}

	if !ing_net.IsPortAvailable(*defServerPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --default-server-port", *defServerPort)
	}

	if *enableSSLPassthrough && !ing_net.IsPortAvailable(*sslProxyPort) {
		return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --ssl-passtrough-proxy-port", *sslProxyPort)
	}

	if !*enableSSLChainCompletion {
		glog.Warningf("Check of SSL certificate chain is disabled (--enable-ssl-chain-completion=false)")
	}

	config := &controller.Configuration{
		APIServerHost:            *apiserverHost,
		KubeConfigFile:           *kubeConfigFile,
		UpdateStatus:             *updateStatus,
		ElectionID:               *electionID,
		EnableProfiling:          *profiling,
		EnableSSLPassthrough:     *enableSSLPassthrough,
		EnableSSLChainCompletion: *enableSSLChainCompletion,
		ResyncPeriod:             *resyncPeriod,
		DefaultService:           *defaultSvc,
		Namespace:                *watchNamespace,
		ConfigMapName:            *configMap,
		TCPConfigMapName:         *tcpConfigMapName,
		UDPConfigMapName:         *udpConfigMapName,
		DefaultSSLCertificate:    *defSSLCertificate,
		DefaultHealthzURL:        *defHealthzURL,
		PublishService:           *publishSvc,
		ForceNamespaceIsolation:  *forceIsolation,
		UpdateStatusOnShutdown:   *updateStatusOnShutdown,
		SortBackends:             *sortBackends,
		UseNodeInternalIP:        *useNodeInternalIP,
		SyncRateLimit:            *syncRateLimit,
		ListenPorts: &ngx_config.ListenPorts{
			Default:  *defServerPort,
			Health:   *healthzPort,
			HTTP:     *httpPort,
			HTTPS:    *httpsPort,
			SSLProxy: *sslProxyPort,
			Status:   *statusPort,
		},
	}

	return false, config, nil
}
<|endoftext|>


<commit_before>package input

import (
	"fmt"
	"gnd.la/i18n"
	"gnd.la/util/types"
	"math"
	"reflect"
	"strconv"
	"strings"
)

// Parser is the interface implemented by types
// that know how to parse themselves from a user
// provided string.
type Parser interface {
	Parse(s string) error
}

// Parse tries to parse an string into the given argument.
// e.g.
//     var f float32
//     Parse("27.5", &f)
//     var width uint
//     Parse("57", &width)
// Supported types are: string, bool, u?int(8|16|32|64)? and float(32|64). If
// the parsed value would overflow the given type, the maximum value
// (or minimum, if it's negative) for the type will be set.
// If arg implements the Parser interface, its Parse method will
// be used instead.
func Parse(val string, arg interface{}) error {
	if parser, ok := arg.(Parser); ok {
		return parser.Parse(val)
	}
	v, err := types.SettableValue(arg)
	if err != nil {
		return err
	}
	return parse(val, v)
}

func parse(val string, v reflect.Value) error {
	// If val is empty, set the value to zero
	if val == "" {
		v.Set(reflect.Zero(v.Type()))
		return nil
	}
	switch v.Type().Kind() {
	case reflect.Bool:
		res := false
		switch strings.ToLower(val) {
		case "", "f", "false", "0", "off":
		case "t", "true", "1", "on":
			res = true
		default:
			return i18n.Errorf("invalid boolean value %q", val)
		}
		v.SetBool(res)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		res, err := strconv.ParseInt(val, 0, 64)
		if err != nil {
			return err
		}
		if v.OverflowInt(res) {
			if res > 0 {
				res = int64(math.Pow(2, float64(8*v.Type().Size()-1)) - 1)
			} else {
				res = -int64(math.Pow(2, float64(8*v.Type().Size()-1)))
			}
		}
		v.SetInt(res)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		res, err := strconv.ParseUint(val, 0, 64)
		if err != nil {
			return err
		}
		if v.OverflowUint(res) {
			res = uint64(math.Pow(2, float64(8*v.Type().Size())) - 1)
		}
		v.SetUint(res)
	case reflect.Float32, reflect.Float64:
		res, err := strconv.ParseFloat(val, 64)
		if err != nil {
			return err
		}
		v.SetFloat(res)
	case reflect.String:
		v.SetString(val)
	default:
		return fmt.Errorf("Invalid argument type passed to Parse(): %s. Please, see the documentation for a list of the supported types.",
			v.Type())
	}
	return nil
}
<commit_msg>Try using the Parser interface in parse()<commit_after>package input

import (
	"fmt"
	"gnd.la/i18n"
	"gnd.la/util/types"
	"math"
	"reflect"
	"strconv"
	"strings"
)

var (
	parserInterface = reflect.TypeOf((*Parser)(nil)).Elem()
)

// Parser is the interface implemented by types
// that know how to parse themselves from a user
// provided string.
type Parser interface {
	Parse(s string) error
}

// Parse tries to parse an string into the given argument.
// e.g.
//     var f float32
//     Parse("27.5", &f)
//     var width uint
//     Parse("57", &width)
// Supported types are: string, bool, u?int(8|16|32|64)? and float(32|64). If
// the parsed value would overflow the given type, the maximum value
// (or minimum, if it's negative) for the type will be set.
// If arg implements the Parser interface, its Parse method will
// be used instead.
func Parse(val string, arg interface{}) error {
	if parser, ok := arg.(Parser); ok {
		return parser.Parse(val)
	}
	v, err := types.SettableValue(arg)
	if err != nil {
		return err
	}
	return parse(val, v)
}

func parse(val string, v reflect.Value) error {
	var err error
	p := v
	// Get Pointer methods
	if p.IsValid() && p.Kind() != reflect.Ptr && p.CanAddr() {
		p = p.Addr()
	}
	if p.Type().Implements(parserInterface) {
		err = p.Interface().(Parser).Parse(val)
		if err == nil {
			return nil
		}
		// Continue with the function, just in case we can
		// still parse the value (e.g. an enum type which defines
		// a Parse() function for accepting raw strings but val
		// is actually a numeric value).
	}
	// If val is empty, set the value to zero
	if val == "" {
		v.Set(reflect.Zero(v.Type()))
		return nil
	}
	switch v.Type().Kind() {
	case reflect.Bool:
		res := false
		switch strings.ToLower(val) {
		case "", "f", "false", "0", "off":
		case "t", "true", "1", "on":
			res = true
		default:
			return i18n.Errorf("invalid boolean value %q", val)
		}
		v.SetBool(res)
		return nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		res, err := strconv.ParseInt(val, 0, 64)
		if err != nil {
			return err
		}
		if v.OverflowInt(res) {
			if res > 0 {
				res = int64(math.Pow(2, float64(8*v.Type().Size()-1)) - 1)
			} else {
				res = -int64(math.Pow(2, float64(8*v.Type().Size()-1)))
			}
		}
		v.SetInt(res)
		return nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		res, err := strconv.ParseUint(val, 0, 64)
		if err != nil {
			return err
		}
		if v.OverflowUint(res) {
			res = uint64(math.Pow(2, float64(8*v.Type().Size())) - 1)
		}
		v.SetUint(res)
		return nil
	case reflect.Float32, reflect.Float64:
		res, err := strconv.ParseFloat(val, 64)
		if err != nil {
			return err
		}
		v.SetFloat(res)
		return nil
	case reflect.String:
		v.SetString(val)
		return nil
	default:
		if err == nil {
			err = fmt.Errorf("Invalid argument type passed to Parse(): %s. Please, see the documentation for a list of the supported types.",
				v.Type())
		}
	}
	return err
}
<|endoftext|>