<commit_before>/*
 * Copyright 2019, EnMasse authors.
 * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
 */

package main

import (
	"context"
	"flag"
	"github.com/99designs/gqlgen/graphql"
	"github.com/99designs/gqlgen/handler"
	adminv1beta2 "github.com/enmasseproject/enmasse/pkg/client/clientset/versioned/typed/admin/v1beta2"
	enmassev1beta1 "github.com/enmasseproject/enmasse/pkg/client/clientset/versioned/typed/enmasse/v1beta1"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/cache"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/metric"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/resolvers"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/server"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/watchers"
	"github.com/enmasseproject/enmasse/pkg/util"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/vektah/gqlparser/gqlerror"
	"k8s.io/client-go/tools/clientcmd"
	"log"
	"net/http"
	"time"
)

/*
console-server - presents a GraphQL API allowing the client to query details of address spaces, addresses,
connections and links.

For development purposes, you can run the console backend outside the container.  See the Makefile target 'run'.
*/

func main() {
	infraNamespace := util.GetEnvOrDefault("NAMESPACE", "enmasse-infra")
	port := util.GetEnvOrDefault("PORT", "8080")
	metricsPort := util.GetEnvOrDefault("METRICS_PORT", "8889")

	var developmentMode = flag.Bool("developmentMode", false,
		"set to true to run console-server outside of the OpenShift container.  It will look for"+
			"manually established routes to agents rather than services.")
	flag.Parse()

	log.Printf("console-server starting\n")

	if *developmentMode {
		log.Printf("Running in DEVELOPMENT MODE.  This mode is not intended for use within the container.\n")
		log.Printf(`Expose addressspace agents to the console server by *manually* running:

oc create route passthrough  --service=console-4f5fcdf

The GraphQL playground is available:
http://localhost:` + port + `/graphql
			`)
	}

	graphqlPlayground := util.GetBooleanEnvOrDefault("GRAPHQL_PLAYGROUND", false)
	promQLRateMetricExpression := util.GetEnvOrDefault("PROMQL_RATE_METRIC_EXPRESSION", "round(rate(unused_label[5m]), 0.01)") // Rate per second, rounded to hundredths
	dumpCachePeriod := util.GetDurationEnvOrDefault("DUMP_CACHE_PERIOD", time.Second*0)
	updateMetricsPeriod := util.GetDurationEnvOrDefault("UPDATE_METRICS_PERIOD", time.Second*5)
	agentCommandDelegateExpiryPeriod := util.GetDurationEnvOrDefault("AGENT_COMMAND_DELEGATE_EXPIRY_PERIOD", time.Minute*5)
	agentAmqpConnectTimeout := util.GetDurationEnvOrDefault("AGENT_AMQP_CONNECT_TIMEOUT", time.Second*10)
	agentAmqpMaxFrameSize := uint32(util.GetUintEnvOrDefault("AGENT_AMQP_MAX_FRAME_SIZE", 0, 32, 4294967295)) // Matches Rhea default
	sessionLifetime := util.GetDurationEnvOrDefault("HTTP_SESSION_LIFETIME", 30*time.Minute)
	sessionIdleTimeout := util.GetDurationEnvOrDefault("HTTP_SESSION_IDLE_TIMEOUT", 5*time.Minute)
	resyncInterval := util.GetDurationEnvOrDefault("RESYNC_INTERVAL", 5*time.Minute)

	log.Printf("Namespace: %s\n", infraNamespace)

	objectCache, err := cache.CreateObjectCache()
	if err != nil {
		panic(err)
	}

	kubeconfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		clientcmd.NewDefaultClientConfigLoadingRules(),
		&clientcmd.ConfigOverrides{},
	)

	config, err := kubeconfig.ClientConfig()
	if err != nil {
		panic(err)
	}

	coreclient, err := enmassev1beta1.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	adminclient, err := adminv1beta2.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	manager := watchers.New(objectCache, resyncInterval, config, infraNamespace, developmentMode, agentCommandDelegateExpiryPeriod, agentAmqpConnectTimeout, agentAmqpMaxFrameSize)
	manager.Start()

	resolver := resolvers.Resolver{
		AdminConfig:  adminclient,
		CoreConfig:   coreclient,
		Cache:        objectCache,
		GetCollector: manager.GetCollector,
	}

	if dumpCachePeriod > 0 {
		server.Schedule(func() {
			_ = objectCache.Dump()
		}, dumpCachePeriod)
	}

	if updateMetricsPeriod.Nanoseconds() > 0 {
		server.Schedule(func() {
			err, updated := metric.UpdateAllMetrics(objectCache, promQLRateMetricExpression)
			if err != nil {
				log.Printf("failed to update metrics, %s", err)
			} else if updated > 0 {
				log.Printf("%d object metric(s) updated", updated)
			}
		}, updateMetricsPeriod)
	}

	queryTimeMetric := prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Name:    "console_query_time_seconds",
		Help:    "The query time in seconds",
		Buckets: prometheus.DefBuckets,
	}, []string{"operationName"})
	queryErrorCountMetric := prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: "console_query_error_total",
		Help: "Number of queries that have ended in error",
	}, []string{"operationName"})
	sessionCountMetric := prometheus.NewGauge(prometheus.GaugeOpts{
		Name: "console_active_sessions",
		Help: "Number of active HTTP sessions",
	})
	prometheus.MustRegister(queryTimeMetric, queryErrorCountMetric, sessionCountMetric)

	queryServer := http.NewServeMux()

	queryEndpoint := "/graphql/query"
	if graphqlPlayground || *developmentMode {
		playground := handler.Playground("GraphQL playground", queryEndpoint)
		queryServer.Handle("/graphql/", playground)
	}

	sessionManager := server.CreateSessionManager(sessionLifetime, sessionIdleTimeout,
		func() { manager.BeginWatching() },
		func() { manager.EndWatching() },
		sessionCountMetric)

	gql := handler.GraphQL(resolvers.NewExecutableSchema(resolvers.Config{Resolvers: &resolver}),
		handler.ErrorPresenter(
			func(ctx context.Context, e error) *gqlerror.Error {
				rctx := graphql.GetRequestContext(ctx)
				if rctx != nil {
					log.Printf("Query error - op: %s query: %s vars: %+v error: %s\n", rctx.OperationName, rctx.RawQuery, rctx.Variables, e)
				}
				queryErrorCountMetric.WithLabelValues(rctx.OperationName).Inc()
				return graphql.DefaultErrorPresenter(ctx, e)
			},
		),
		handler.RequestMiddleware(func(ctx context.Context, next func(ctx context.Context) []byte) []byte {

			loggedOnUser := "<unknown>"
			start := time.Now()
			result := next(ctx)

			loggedOnUser = server.UpdateAccessControllerState(ctx, loggedOnUser, sessionManager)

			rctx := graphql.GetRequestContext(ctx)
			if rctx != nil {
				since := time.Since(start)
				log.Printf("[%s] Query execution - op: %s %s\n", loggedOnUser, rctx.OperationName, since)
				queryTimeMetric.WithLabelValues(rctx.OperationName).Observe(since.Seconds())
			}
			return result
		}),
	)

	if *developmentMode {
		queryServer.Handle(queryEndpoint, server.DevelopmentHandler(gql, sessionManager, config.BearerToken))
	} else {
		queryServer.Handle(queryEndpoint, server.AuthHandler(gql, sessionManager))
	}

	go func() {
		err = http.ListenAndServe("127.0.0.1:"+port, sessionManager.LoadAndSave(queryServer))
		if err != nil {
			panic(err.Error())
		}
	}()

	metricsServer := http.NewServeMux()

	metricsServer.Handle("/metrics", promhttp.Handler())
	err = http.ListenAndServe(":"+metricsPort, metricsServer)
	if err != nil {
		panic(err.Error())
	}

}
<commit_msg>console server - log using UTC datestamps to aid correlation with other logs (#4034)<commit_after>/*
 * Copyright 2019, EnMasse authors.
 * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
 */

package main

import (
	"context"
	"flag"
	"fmt"
	"github.com/99designs/gqlgen/graphql"
	"github.com/99designs/gqlgen/handler"
	adminv1beta2 "github.com/enmasseproject/enmasse/pkg/client/clientset/versioned/typed/admin/v1beta2"
	enmassev1beta1 "github.com/enmasseproject/enmasse/pkg/client/clientset/versioned/typed/enmasse/v1beta1"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/cache"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/metric"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/resolvers"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/server"
	"github.com/enmasseproject/enmasse/pkg/consolegraphql/watchers"
	"github.com/enmasseproject/enmasse/pkg/util"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/vektah/gqlparser/gqlerror"
	"k8s.io/client-go/tools/clientcmd"
	"log"
	"net/http"
	"time"
)

/*
console-server - presents a GraphQL API allowing the client to query details of address spaces, addresses,
connections and links.

For development purposes, you can run the console backend outside the container.  See the Makefile target 'run'.
*/

type logWriter struct {
}

func (writer logWriter) Write(bytes []byte) (int, error) {
	return fmt.Print(time.Now().UTC().Format("2006-01-02T15:04:05.999Z") + " " + string(bytes))
}

func main() {
	log.SetFlags(0)
	log.SetOutput(new(logWriter))

	infraNamespace := util.GetEnvOrDefault("NAMESPACE", "enmasse-infra")
	port := util.GetEnvOrDefault("PORT", "8080")
	metricsPort := util.GetEnvOrDefault("METRICS_PORT", "8889")

	var developmentMode = flag.Bool("developmentMode", false,
		"set to true to run console-server outside of the OpenShift container.  It will look for"+
			"manually established routes to agents rather than services.")
	flag.Parse()

	log.Printf("console-server starting\n")

	if *developmentMode {
		log.Printf("Running in DEVELOPMENT MODE.  This mode is not intended for use within the container.\n")
		log.Printf(`Expose addressspace agents to the console server by *manually* running:

oc create route passthrough  --service=console-4f5fcdf

The GraphQL playground is available:
http://localhost:` + port + `/graphql
			`)
	}

	graphqlPlayground := util.GetBooleanEnvOrDefault("GRAPHQL_PLAYGROUND", false)
	promQLRateMetricExpression := util.GetEnvOrDefault("PROMQL_RATE_METRIC_EXPRESSION", "round(rate(unused_label[5m]), 0.01)") // Rate per second, rounded to hundredths
	dumpCachePeriod := util.GetDurationEnvOrDefault("DUMP_CACHE_PERIOD", time.Second*0)
	updateMetricsPeriod := util.GetDurationEnvOrDefault("UPDATE_METRICS_PERIOD", time.Second*5)
	agentCommandDelegateExpiryPeriod := util.GetDurationEnvOrDefault("AGENT_COMMAND_DELEGATE_EXPIRY_PERIOD", time.Minute*5)
	agentAmqpConnectTimeout := util.GetDurationEnvOrDefault("AGENT_AMQP_CONNECT_TIMEOUT", time.Second*10)
	agentAmqpMaxFrameSize := uint32(util.GetUintEnvOrDefault("AGENT_AMQP_MAX_FRAME_SIZE", 0, 32, 4294967295)) // Matches Rhea default
	sessionLifetime := util.GetDurationEnvOrDefault("HTTP_SESSION_LIFETIME", 30*time.Minute)
	sessionIdleTimeout := util.GetDurationEnvOrDefault("HTTP_SESSION_IDLE_TIMEOUT", 5*time.Minute)
	resyncInterval := util.GetDurationEnvOrDefault("RESYNC_INTERVAL", 5*time.Minute)

	log.Printf("Namespace: %s\n", infraNamespace)

	objectCache, err := cache.CreateObjectCache()
	if err != nil {
		panic(err)
	}

	kubeconfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		clientcmd.NewDefaultClientConfigLoadingRules(),
		&clientcmd.ConfigOverrides{},
	)

	config, err := kubeconfig.ClientConfig()
	if err != nil {
		panic(err)
	}

	coreclient, err := enmassev1beta1.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	adminclient, err := adminv1beta2.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	manager := watchers.New(objectCache, resyncInterval, config, infraNamespace, developmentMode, agentCommandDelegateExpiryPeriod, agentAmqpConnectTimeout, agentAmqpMaxFrameSize)
	manager.Start()

	resolver := resolvers.Resolver{
		AdminConfig:  adminclient,
		CoreConfig:   coreclient,
		Cache:        objectCache,
		GetCollector: manager.GetCollector,
	}

	if dumpCachePeriod > 0 {
		server.Schedule(func() {
			_ = objectCache.Dump()
		}, dumpCachePeriod)
	}

	if updateMetricsPeriod.Nanoseconds() > 0 {
		server.Schedule(func() {
			err, updated := metric.UpdateAllMetrics(objectCache, promQLRateMetricExpression)
			if err != nil {
				log.Printf("failed to update metrics, %s", err)
			} else if updated > 0 {
				log.Printf("%d object metric(s) updated", updated)
			}
		}, updateMetricsPeriod)
	}

	queryTimeMetric := prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Name:    "console_query_time_seconds",
		Help:    "The query time in seconds",
		Buckets: prometheus.DefBuckets,
	}, []string{"operationName"})
	queryErrorCountMetric := prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: "console_query_error_total",
		Help: "Number of queries that have ended in error",
	}, []string{"operationName"})
	sessionCountMetric := prometheus.NewGauge(prometheus.GaugeOpts{
		Name: "console_active_sessions",
		Help: "Number of active HTTP sessions",
	})
	prometheus.MustRegister(queryTimeMetric, queryErrorCountMetric, sessionCountMetric)

	queryServer := http.NewServeMux()

	queryEndpoint := "/graphql/query"
	if graphqlPlayground || *developmentMode {
		playground := handler.Playground("GraphQL playground", queryEndpoint)
		queryServer.Handle("/graphql/", playground)
	}

	sessionManager := server.CreateSessionManager(sessionLifetime, sessionIdleTimeout,
		func() { manager.BeginWatching() },
		func() { manager.EndWatching() },
		sessionCountMetric)

	gql := handler.GraphQL(resolvers.NewExecutableSchema(resolvers.Config{Resolvers: &resolver}),
		handler.ErrorPresenter(
			func(ctx context.Context, e error) *gqlerror.Error {
				rctx := graphql.GetRequestContext(ctx)
				if rctx != nil {
					log.Printf("Query error - op: %s query: %s vars: %+v error: %s\n", rctx.OperationName, rctx.RawQuery, rctx.Variables, e)
				}
				queryErrorCountMetric.WithLabelValues(rctx.OperationName).Inc()
				return graphql.DefaultErrorPresenter(ctx, e)
			},
		),
		handler.RequestMiddleware(func(ctx context.Context, next func(ctx context.Context) []byte) []byte {

			loggedOnUser := "<unknown>"
			start := time.Now()
			result := next(ctx)

			loggedOnUser = server.UpdateAccessControllerState(ctx, loggedOnUser, sessionManager)

			rctx := graphql.GetRequestContext(ctx)
			if rctx != nil {
				since := time.Since(start)
				log.Printf("[%s] Query execution - op: %s %s\n", loggedOnUser, rctx.OperationName, since)
				queryTimeMetric.WithLabelValues(rctx.OperationName).Observe(since.Seconds())
			}
			return result
		}),
	)

	if *developmentMode {
		queryServer.Handle(queryEndpoint, server.DevelopmentHandler(gql, sessionManager, config.BearerToken))
	} else {
		queryServer.Handle(queryEndpoint, server.AuthHandler(gql, sessionManager))
	}

	go func() {
		err = http.ListenAndServe("127.0.0.1:"+port, sessionManager.LoadAndSave(queryServer))
		if err != nil {
			panic(err.Error())
		}
	}()

	metricsServer := http.NewServeMux()

	metricsServer.Handle("/metrics", promhttp.Handler())
	err = http.ListenAndServe(":"+metricsPort, metricsServer)
	if err != nil {
		panic(err.Error())
	}

}
<|endoftext|>


<commit_before>/*
Copyright 2018 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 (
	"context"
	"fmt"
	"testing"

	"k8s.io/api/networking/v1beta1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/ingress-gce/pkg/e2e"
	"k8s.io/ingress-gce/pkg/fuzz"
	"k8s.io/ingress-gce/pkg/fuzz/features"
	"k8s.io/ingress-gce/pkg/utils/common"
)

func TestBasic(t *testing.T) {
	t.Parallel()

	port80 := intstr.FromInt(80)

	for _, tc := range []struct {
		desc string
		ing  *v1beta1.Ingress
	}{
		{
			desc: "http default backend",
			ing: fuzz.NewIngressBuilder("", "ingress-1", "").
				DefaultBackend("service-1", port80).
				Build(),
		},
		{
			desc: "http one path",
			ing: fuzz.NewIngressBuilder("", "ingress-1", "").
				AddPath("test.com", "/", "service-1", port80).
				Build(),
		},
		{
			desc: "http multiple paths",
			ing: fuzz.NewIngressBuilder("", "ingress-1", "").
				AddPath("test.com", "/foo", "service-1", port80).
				AddPath("test.com", "/bar", "service-1", port80).
				Build(),
		},
	} {
		tc := tc // Capture tc as we are running this in parallel.
		Framework.RunWithSandbox(tc.desc, t, func(t *testing.T, s *e2e.Sandbox) {
			t.Parallel()

			ctx := context.Background()

			_, err := e2e.CreateEchoService(s, "service-1", nil)
			if err != nil {
				t.Fatalf("error creating echo service: %v", err)
			}
			t.Logf("Echo service created (%s/%s)", s.Namespace, "service-1")

			crud := e2e.IngressCRUD{C: Framework.Clientset}
			tc.ing.Namespace = s.Namespace // namespace depends on sandbox
			if _, err = crud.Create(tc.ing); err != nil {
				t.Fatalf("error creating Ingress spec: %v", err)
			}
			t.Logf("Ingress created (%s/%s)", s.Namespace, tc.ing.Name)

			ing, err := e2e.WaitForIngress(s, tc.ing, nil)
			if err != nil {
				t.Fatalf("error waiting for Ingress to stabilize: %v", err)
			}
			t.Logf("GCLB resources createdd (%s/%s)", s.Namespace, tc.ing.Name)

			// Perform whitebox testing.
			gclb, err := e2e.WhiteboxTest(ing, s, Framework.Cloud, "")
			if err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s/%s, ...) = %v, want nil", ing.Namespace, ing.Name, err)
			}

			deleteOptions := &fuzz.GCLBDeleteOptions{
				SkipDefaultBackend: true,
			}
			if err := e2e.WaitForIngressDeletion(ctx, gclb, s, ing, deleteOptions); err != nil {
				t.Errorf("e2e.WaitForIngressDeletion(..., %q, nil) = %v, want nil", ing.Name, err)
			}
		})
	}
}

// TestBasicStaticIP tests that the static-ip annotation works as expected.
func TestBasicStaticIP(t *testing.T) {
	ctx := context.Background()
	t.Parallel()

	Framework.RunWithSandbox("static-ip", t, func(t *testing.T, s *e2e.Sandbox) {
		_, err := e2e.CreateEchoService(s, "service-1", nil)
		if err != nil {
			t.Fatalf("e2e.CreateEchoService(s, service-1, nil) = _, %v; want _, nil", err)
		}

		addrName := fmt.Sprintf("test-addr-%s", s.Namespace)
		if err := e2e.NewGCPAddress(s, addrName); err != nil {
			t.Fatalf("e2e.NewGCPAddress(..., %s) = %v, want nil", addrName, err)
		}
		defer e2e.DeleteGCPAddress(s, addrName)

		testIng := fuzz.NewIngressBuilder(s.Namespace, "ingress-1", "").
			DefaultBackend("service-1", intstr.FromInt(80)).
			AddStaticIP(addrName).
			Build()
		crud := e2e.IngressCRUD{C: Framework.Clientset}
		testIng, err = crud.Create(testIng)
		if err != nil {
			t.Fatalf("error creating Ingress spec: %v", err)
		}
		t.Logf("Ingress %s/%s created", s.Namespace, testIng.Name)

		testIng, err = e2e.WaitForIngress(s, testIng, nil)
		if err != nil {
			t.Fatalf("e2e.WaitForIngress(s, %q) = _, %v; want _, nil", testIng.Name, err)
		}
		if len(testIng.Status.LoadBalancer.Ingress) < 1 {
			t.Fatalf("Ingress does not have an IP: %+v", testIng.Status)
		}

		vip := testIng.Status.LoadBalancer.Ingress[0].IP
		params := &fuzz.GCLBForVIPParams{
			VIP:        vip,
			Validators: fuzz.FeatureValidators([]fuzz.Feature{features.SecurityPolicy}),
		}
		gclb, err := fuzz.GCLBForVIP(ctx, Framework.Cloud, params)
		if err != nil {
			t.Fatalf("fuzz.GCLBForVIP(..., %q, %q) = _, %v; want _, nil", vip, features.SecurityPolicy, err)
		}

		if err := e2e.WaitForIngressDeletion(ctx, gclb, s, testIng, deleteOptions); err != nil {
			t.Errorf("e2e.WaitForIngressDeletion(..., %q, nil) = %v, want nil", testIng.Name, err)
		}
	})

	// TODO(rramkumar): Add transition
}

// TestEdge exercises some basic edge cases that previously have caused bugs.
func TestEdge(t *testing.T) {
	t.Parallel()

	port80 := intstr.FromInt(80)

	for _, tc := range []struct {
		desc string
		ing  *v1beta1.Ingress
	}{
		{
			desc: "long ingress name",
			ing: fuzz.NewIngressBuilder("", "long-ingress-name", "").
				DefaultBackend("service-1", port80).
				Build(),
		},
	} {
		tc := tc // Capture tc as we are running this in parallel.
		Framework.RunWithSandbox(tc.desc, t, func(t *testing.T, s *e2e.Sandbox) {
			t.Parallel()

			ctx := context.Background()

			_, err := e2e.CreateEchoService(s, "service-1", nil)
			if err != nil {
				t.Fatalf("error creating echo service: %v", err)
			}
			t.Logf("Echo service created (%s/%s)", s.Namespace, "service-1")
			crud := e2e.IngressCRUD{C: Framework.Clientset}
			tc.ing.Namespace = s.Namespace // namespace depends on sandbox
			if _, err = crud.Create(tc.ing); err != nil {
				t.Fatalf("error creating Ingress spec: %v", err)
			}
			t.Logf("Ingress created (%s/%s)", s.Namespace, tc.ing.Name)

			ing, err := e2e.WaitForIngress(s, tc.ing, nil)
			if err != nil {
				t.Fatalf("error waiting for Ingress to stabilize: %v", err)
			}
			t.Logf("GCLB resources createdd (%s/%s)", s.Namespace, tc.ing.Name)

			// Perform whitebox testing.
			gclb, err := e2e.WhiteboxTest(ing, s, Framework.Cloud, "")
			if err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s/%s, ...) = %v, want nil", ing.Namespace, ing.Name, err)
			}

			deleteOptions := &fuzz.GCLBDeleteOptions{
				SkipDefaultBackend: true,
			}
			if err := e2e.WaitForIngressDeletion(ctx, gclb, s, ing, deleteOptions); err != nil {
				t.Errorf("e2e.WaitForIngressDeletion(..., %q, nil) = %v, want nil", ing.Name, err)
			}
		})
	}
}

// TestFrontendResourceDeletion asserts that unused GCP frontend resources are
// deleted. This also tests that necessary GCP frontend resources exist.
func TestFrontendResourceDeletion(t *testing.T) {
	t.Parallel()
	port80 := intstr.FromInt(80)
	svcName := "service-1"
	host := "foo.com"

	// All the test cases create an ingress with a HTTP + HTTPS load-balancer
	// at the beginning of the test and turnoff these based on the testcase params.
	for _, tc := range []struct {
		desc         string
		disableHTTP  bool
		disableHTTPS bool
	}{
		// Note that disabling both HTTP & HTTPS would result in a sync error, so excluded.
		{"http only", false, true},
		{"https only", true, false},
	} {
		tc := tc
		Framework.RunWithSandbox(tc.desc, t, func(t *testing.T, s *e2e.Sandbox) {
			t.Parallel()
			ctx := context.Background()

			_, err := e2e.CreateEchoService(s, svcName, nil)
			if err != nil {
				t.Fatalf("CreateEchoService(_, %q, nil): %v, want nil", svcName, err)
			}
			t.Logf("Echo service created (%s/%s)", s.Namespace, svcName)

			// Create SSL certificate.
			certName := fmt.Sprintf("cert-1")
			cert, err := e2e.NewCert(certName, host, e2e.K8sCert, false)
			if err != nil {
				t.Fatalf("e2e.NewCert(%q, %q, _, %t) = %v, want nil", certName, host, false, err)
			}
			if err := cert.Create(s); err != nil {
				t.Fatalf("cert.Create(_) = %v, want nil, error creating cert %s", err, cert.Name)
			}
			t.Logf("Cert created %s", certName)
			defer cert.Delete(s)

			ing := fuzz.NewIngressBuilder(s.Namespace, "ing1", "").
				AddPath(host, "/", svcName, port80).AddTLS([]string{}, cert.Name).Build()
			ingKey := common.NamespacedName(ing)

			crud := e2e.IngressCRUD{C: Framework.Clientset}
			if _, err := crud.Create(ing); err != nil {
				t.Fatalf("crud.Create(%s) = %v, want nil; Ingress: %v", ingKey, err, ing)
			}
			t.Logf("Ingress created (%s)", ingKey)
			if ing, err = e2e.WaitForIngress(s, ing, &e2e.WaitForIngressOptions{ExpectUnreachable: true}); err != nil {
				t.Fatalf("error waiting for Ingress %s to stabilize: %v", ingKey, err)
			}
			gclb, err := e2e.WhiteboxTest(ing, s, Framework.Cloud, "")
			if err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s, ...)", ingKey)
			}

			// Update ingress with desired frontend resource configuration.
			ingBuilder := fuzz.NewIngressBuilderFromExisting(ing)
			if tc.disableHTTP {
				ingBuilder = ingBuilder.SetAllowHttp(false)
			}
			if tc.disableHTTPS {
				ingBuilder = ingBuilder.SetTLS(nil)
			}
			ing = ingBuilder.Build()

			if _, err := crud.Update(ing); err != nil {
				t.Fatalf("Update(%s) = %v, want nil; ingress: %v", ingKey, err, ing)
			}
			t.Logf("Ingress updated (%s)", ingKey)
			if ing, err = e2e.WaitForIngress(s, ing, &e2e.WaitForIngressOptions{ExpectUnreachable: true}); err != nil {
				t.Fatalf("error waiting for Ingress %s to stabilize: %v", ingKey, err)
			}

			deleteOptions := &fuzz.GCLBDeleteOptions{
				SkipDefaultBackend:          true,
				CheckHttpFrontendResources:  tc.disableHTTP,
				CheckHttpsFrontendResources: tc.disableHTTPS,
			}
			// Wait for unused frontend resources to be deleted.
			if err := e2e.WaitForFrontendResourceDeletion(ctx, Framework.Cloud, gclb, deleteOptions); err != nil {
				t.Errorf("e2e.WaitForIngressDeletion(..., %q, _) = %v, want nil", ingKey, err)
			}
			if gclb, err = e2e.WhiteboxTest(ing, s, Framework.Cloud, ""); err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s, ...) = %v, want nil", ingKey, err)
			}
			deleteOptions = &fuzz.GCLBDeleteOptions{
				SkipDefaultBackend: true,
			}
			if err := e2e.WaitForIngressDeletion(ctx, gclb, s, ing, deleteOptions); err != nil {
				t.Errorf("e2e.WaitForIngressDeletion(..., %q, _) = %v, want nil", ingKey, err)
			}
		})
	}
}
<commit_msg>Add test to assert that ingress VIP is unchanged<commit_after>/*
Copyright 2018 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 (
	"context"
	"fmt"
	"testing"

	"k8s.io/api/networking/v1beta1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/ingress-gce/pkg/e2e"
	"k8s.io/ingress-gce/pkg/fuzz"
	"k8s.io/ingress-gce/pkg/fuzz/features"
	"k8s.io/ingress-gce/pkg/utils/common"
)

func TestBasic(t *testing.T) {
	t.Parallel()

	port80 := intstr.FromInt(80)

	for _, tc := range []struct {
		desc string
		ing  *v1beta1.Ingress
	}{
		{
			desc: "http default backend",
			ing: fuzz.NewIngressBuilder("", "ingress-1", "").
				DefaultBackend("service-1", port80).
				Build(),
		},
		{
			desc: "http one path",
			ing: fuzz.NewIngressBuilder("", "ingress-1", "").
				AddPath("test.com", "/", "service-1", port80).
				Build(),
		},
		{
			desc: "http multiple paths",
			ing: fuzz.NewIngressBuilder("", "ingress-1", "").
				AddPath("test.com", "/foo", "service-1", port80).
				AddPath("test.com", "/bar", "service-1", port80).
				Build(),
		},
	} {
		tc := tc // Capture tc as we are running this in parallel.
		Framework.RunWithSandbox(tc.desc, t, func(t *testing.T, s *e2e.Sandbox) {
			t.Parallel()

			ctx := context.Background()

			_, err := e2e.CreateEchoService(s, "service-1", nil)
			if err != nil {
				t.Fatalf("error creating echo service: %v", err)
			}
			t.Logf("Echo service created (%s/%s)", s.Namespace, "service-1")

			crud := e2e.IngressCRUD{C: Framework.Clientset}
			tc.ing.Namespace = s.Namespace // namespace depends on sandbox
			if _, err = crud.Create(tc.ing); err != nil {
				t.Fatalf("error creating Ingress spec: %v", err)
			}
			t.Logf("Ingress created (%s/%s)", s.Namespace, tc.ing.Name)

			ing, err := e2e.WaitForIngress(s, tc.ing, nil)
			if err != nil {
				t.Fatalf("error waiting for Ingress to stabilize: %v", err)
			}
			t.Logf("GCLB resources createdd (%s/%s)", s.Namespace, tc.ing.Name)

			// Perform whitebox testing.
			gclb, err := e2e.WhiteboxTest(ing, s, Framework.Cloud, "")
			if err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s/%s, ...) = %v, want nil", ing.Namespace, ing.Name, err)
			}

			deleteOptions := &fuzz.GCLBDeleteOptions{
				SkipDefaultBackend: true,
			}
			if err := e2e.WaitForIngressDeletion(ctx, gclb, s, ing, deleteOptions); err != nil {
				t.Errorf("e2e.WaitForIngressDeletion(..., %q, nil) = %v, want nil", ing.Name, err)
			}
		})
	}
}

// TestBasicStaticIP tests that the static-ip annotation works as expected.
func TestBasicStaticIP(t *testing.T) {
	ctx := context.Background()
	t.Parallel()

	Framework.RunWithSandbox("static-ip", t, func(t *testing.T, s *e2e.Sandbox) {
		_, err := e2e.CreateEchoService(s, "service-1", nil)
		if err != nil {
			t.Fatalf("e2e.CreateEchoService(s, service-1, nil) = _, %v; want _, nil", err)
		}

		addrName := fmt.Sprintf("test-addr-%s", s.Namespace)
		if err := e2e.NewGCPAddress(s, addrName); err != nil {
			t.Fatalf("e2e.NewGCPAddress(..., %s) = %v, want nil", addrName, err)
		}
		defer e2e.DeleteGCPAddress(s, addrName)

		testIng := fuzz.NewIngressBuilder(s.Namespace, "ingress-1", "").
			DefaultBackend("service-1", intstr.FromInt(80)).
			AddStaticIP(addrName).
			Build()
		crud := e2e.IngressCRUD{C: Framework.Clientset}
		testIng, err = crud.Create(testIng)
		if err != nil {
			t.Fatalf("error creating Ingress spec: %v", err)
		}
		t.Logf("Ingress %s/%s created", s.Namespace, testIng.Name)

		testIng, err = e2e.WaitForIngress(s, testIng, nil)
		if err != nil {
			t.Fatalf("e2e.WaitForIngress(s, %q) = _, %v; want _, nil", testIng.Name, err)
		}
		if len(testIng.Status.LoadBalancer.Ingress) < 1 {
			t.Fatalf("Ingress does not have an IP: %+v", testIng.Status)
		}

		vip := testIng.Status.LoadBalancer.Ingress[0].IP
		params := &fuzz.GCLBForVIPParams{
			VIP:        vip,
			Validators: fuzz.FeatureValidators([]fuzz.Feature{features.SecurityPolicy}),
		}
		gclb, err := fuzz.GCLBForVIP(ctx, Framework.Cloud, params)
		if err != nil {
			t.Fatalf("fuzz.GCLBForVIP(..., %q, %q) = _, %v; want _, nil", vip, features.SecurityPolicy, err)
		}

		if err := e2e.WaitForIngressDeletion(ctx, gclb, s, testIng, deleteOptions); err != nil {
			t.Errorf("e2e.WaitForIngressDeletion(..., %q, nil) = %v, want nil", testIng.Name, err)
		}
	})

	// TODO(rramkumar): Add transition
}

// TestEdge exercises some basic edge cases that previously have caused bugs.
func TestEdge(t *testing.T) {
	t.Parallel()

	port80 := intstr.FromInt(80)

	for _, tc := range []struct {
		desc string
		ing  *v1beta1.Ingress
	}{
		{
			desc: "long ingress name",
			ing: fuzz.NewIngressBuilder("", "long-ingress-name", "").
				DefaultBackend("service-1", port80).
				Build(),
		},
	} {
		tc := tc // Capture tc as we are running this in parallel.
		Framework.RunWithSandbox(tc.desc, t, func(t *testing.T, s *e2e.Sandbox) {
			t.Parallel()

			ctx := context.Background()

			_, err := e2e.CreateEchoService(s, "service-1", nil)
			if err != nil {
				t.Fatalf("error creating echo service: %v", err)
			}
			t.Logf("Echo service created (%s/%s)", s.Namespace, "service-1")
			crud := e2e.IngressCRUD{C: Framework.Clientset}
			tc.ing.Namespace = s.Namespace // namespace depends on sandbox
			if _, err = crud.Create(tc.ing); err != nil {
				t.Fatalf("error creating Ingress spec: %v", err)
			}
			t.Logf("Ingress created (%s/%s)", s.Namespace, tc.ing.Name)

			ing, err := e2e.WaitForIngress(s, tc.ing, nil)
			if err != nil {
				t.Fatalf("error waiting for Ingress to stabilize: %v", err)
			}
			t.Logf("GCLB resources createdd (%s/%s)", s.Namespace, tc.ing.Name)

			// Perform whitebox testing.
			gclb, err := e2e.WhiteboxTest(ing, s, Framework.Cloud, "")
			if err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s/%s, ...) = %v, want nil", ing.Namespace, ing.Name, err)
			}

			deleteOptions := &fuzz.GCLBDeleteOptions{
				SkipDefaultBackend: true,
			}
			if err := e2e.WaitForIngressDeletion(ctx, gclb, s, ing, deleteOptions); err != nil {
				t.Errorf("e2e.WaitForIngressDeletion(..., %q, nil) = %v, want nil", ing.Name, err)
			}
		})
	}
}

// TestFrontendResourceDeletion asserts that unused GCP frontend resources are
// deleted. This also tests that necessary GCP frontend resources exist.
func TestFrontendResourceDeletion(t *testing.T) {
	t.Parallel()
	port80 := intstr.FromInt(80)
	svcName := "service-1"
	host := "foo.com"

	// All the test cases create an ingress with a HTTP + HTTPS load-balancer
	// at the beginning of the test and turnoff these based on the testcase params.
	for _, tc := range []struct {
		desc         string
		disableHTTP  bool
		disableHTTPS bool
	}{
		// Note that disabling both HTTP & HTTPS would result in a sync error, so excluded.
		{"http only", false, true},
		{"https only", true, false},
	} {
		tc := tc
		Framework.RunWithSandbox(tc.desc, t, func(t *testing.T, s *e2e.Sandbox) {
			t.Parallel()
			ctx := context.Background()

			_, err := e2e.CreateEchoService(s, svcName, nil)
			if err != nil {
				t.Fatalf("CreateEchoService(_, %q, nil): %v, want nil", svcName, err)
			}
			t.Logf("Echo service created (%s/%s)", s.Namespace, svcName)

			// Create SSL certificate.
			certName := fmt.Sprintf("cert-1")
			cert, err := e2e.NewCert(certName, host, e2e.K8sCert, false)
			if err != nil {
				t.Fatalf("e2e.NewCert(%q, %q, _, %t) = %v, want nil", certName, host, false, err)
			}
			if err := cert.Create(s); err != nil {
				t.Fatalf("cert.Create(_) = %v, want nil, error creating cert %s", err, cert.Name)
			}
			t.Logf("Cert created %s", certName)
			defer cert.Delete(s)

			ing := fuzz.NewIngressBuilder(s.Namespace, "ing1", "").
				AddPath(host, "/", svcName, port80).AddTLS([]string{}, cert.Name).Build()
			ingKey := common.NamespacedName(ing)

			crud := e2e.IngressCRUD{C: Framework.Clientset}
			if _, err := crud.Create(ing); err != nil {
				t.Fatalf("crud.Create(%s) = %v, want nil; Ingress: %v", ingKey, err, ing)
			}
			t.Logf("Ingress created (%s)", ingKey)
			if ing, err = e2e.WaitForIngress(s, ing, &e2e.WaitForIngressOptions{ExpectUnreachable: true}); err != nil {
				t.Fatalf("error waiting for Ingress %s to stabilize: %v", ingKey, err)
			}
			gclb, err := e2e.WhiteboxTest(ing, s, Framework.Cloud, "")
			if err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s, ...)", ingKey)
			}

			// Update ingress with desired frontend resource configuration.
			ingBuilder := fuzz.NewIngressBuilderFromExisting(ing)
			if tc.disableHTTP {
				ingBuilder = ingBuilder.SetAllowHttp(false)
			}
			if tc.disableHTTPS {
				ingBuilder = ingBuilder.SetTLS(nil)
			}
			ing = ingBuilder.Build()

			if _, err := crud.Update(ing); err != nil {
				t.Fatalf("Update(%s) = %v, want nil; ingress: %v", ingKey, err, ing)
			}
			t.Logf("Ingress updated (%s)", ingKey)
			if ing, err = e2e.WaitForIngress(s, ing, &e2e.WaitForIngressOptions{ExpectUnreachable: true}); err != nil {
				t.Fatalf("error waiting for Ingress %s to stabilize: %v", ingKey, err)
			}

			deleteOptions := &fuzz.GCLBDeleteOptions{
				SkipDefaultBackend:          true,
				CheckHttpFrontendResources:  tc.disableHTTP,
				CheckHttpsFrontendResources: tc.disableHTTPS,
			}
			// Wait for unused frontend resources to be deleted.
			if err := e2e.WaitForFrontendResourceDeletion(ctx, Framework.Cloud, gclb, deleteOptions); err != nil {
				t.Errorf("e2e.WaitForIngressDeletion(..., %q, _) = %v, want nil", ingKey, err)
			}
			if gclb, err = e2e.WhiteboxTest(ing, s, Framework.Cloud, ""); err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s, ...) = %v, want nil", ingKey, err)
			}

			expectedVIP := ing.Status.LoadBalancer.Ingress[0].IP
			// Re-enable http/https and verify that the ingress uses same VIP.
			if ing, err = crud.Get(ing.Namespace, ing.Name); err != nil {
				t.Fatalf("crud.Get(%s) = %v, want nil", ingKey, err)
			}
			ingBuilder = fuzz.NewIngressBuilderFromExisting(ing)
			if tc.disableHTTP {
				ingBuilder = ingBuilder.SetAllowHttp(true)
			}
			if tc.disableHTTPS {
				ingBuilder.SetTLS([]v1beta1.IngressTLS{
					{
						Hosts:      []string{},
						SecretName: cert.Name,
					},
				})
			}
			ing = ingBuilder.Build()
			if _, err := crud.Update(ing); err != nil {
				t.Fatalf("Update(%s) = %v, want nil; ingress: %v", ingKey, err, ing)
			}
			t.Logf("Ingress updated (%s)", ingKey)
			if ing, err = e2e.WaitForIngress(s, ing, &e2e.WaitForIngressOptions{ExpectUnreachable: true}); err != nil {
				t.Fatalf("error waiting for Ingress %s to stabilize: %v", ingKey, err)
			}
			gclb, err = e2e.WhiteboxTest(ing, s, Framework.Cloud, "")
			if err != nil {
				t.Fatalf("e2e.WhiteboxTest(%s, ...)", ingKey)
			}
			// Verify that ingress VIP is retained.
			gotVIP := ing.Status.LoadBalancer.Ingress[0].IP
			if expectedVIP != gotVIP {
				t.Fatalf("Two separate VIPs are created. expected %s, got %s", expectedVIP, gotVIP)
			}

			deleteOptions = &fuzz.GCLBDeleteOptions{
				SkipDefaultBackend: true,
			}
			if err := e2e.WaitForIngressDeletion(ctx, gclb, s, ing, deleteOptions); err != nil {
				t.Errorf("e2e.WaitForIngressDeletion(..., %q, _) = %v, want nil", ingKey, err)
			}
		})
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"

	"github.com/nabeken/golang-sqs-worker-example/worker"

	"github.com/stripe/aws-go/aws"
	"github.com/stripe/aws-go/gen/sqs"
)

var flagQueue = flag.String("q", "example", "specify a queue name")

func Print(msg *sqs.Message) error {
	fmt.Println(*msg.Body)
	return nil
}

func main() {
	flag.Parse()

	q, err := worker.NewSQSQueue(
		sqs.New(aws.DetectCreds("", "", ""), "ap-northeast-1", nil),
		*flagQueue,
	)
	if err != nil {
		log.Fatal(err)
	}

	worker.Start(q, worker.HandlerFunc(Print))
}
<commit_msg>Fix import order<commit_after>package main

import (
	"flag"
	"fmt"
	"log"

	"github.com/stripe/aws-go/aws"
	"github.com/stripe/aws-go/gen/sqs"

	"github.com/nabeken/golang-sqs-worker-example/worker"
)

var flagQueue = flag.String("q", "example", "specify a queue name")

func Print(msg *sqs.Message) error {
	fmt.Println(*msg.Body)
	return nil
}

func main() {
	flag.Parse()

	q, err := worker.NewSQSQueue(
		sqs.New(aws.DetectCreds("", "", ""), "ap-northeast-1", nil),
		*flagQueue,
	)
	if err != nil {
		log.Fatal(err)
	}

	worker.Start(q, worker.HandlerFunc(Print))
}
<|endoftext|>


<commit_before>package command

import (
	"flag"
	"fmt"
	"strconv"
	"strings"

	"github.com/Shopify/sarama"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/gocli"
	"github.com/funkygao/golib/color"
)

type Clusters struct {
	Ui  cli.Ui
	Cmd string

	verbose           bool
	registeredBrokers bool
}

// TODO cluster info will contain desciption,owner,etc.
func (this *Clusters) Run(args []string) (exitCode int) {
	var (
		addCluster  string
		setMode     bool
		verifyMode  bool
		clusterName string
		clusterPath string
		zone        string
		priority    int
		replicas    int
		addBroker   string
		nickname    string
		delBroker   int
	)
	cmdFlags := flag.NewFlagSet("clusters", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&zone, "z", "", "")
	cmdFlags.StringVar(&addCluster, "add", "", "")
	cmdFlags.BoolVar(&setMode, "s", false, "")
	cmdFlags.StringVar(&clusterName, "c", "", "")
	cmdFlags.StringVar(&clusterPath, "p", "", "")
	cmdFlags.BoolVar(&this.verbose, "l", false, "")
	cmdFlags.IntVar(&replicas, "replicas", -1, "")
	cmdFlags.IntVar(&priority, "priority", -1, "")
	cmdFlags.StringVar(&addBroker, "addbroker", "", "")
	cmdFlags.StringVar(&nickname, "nickname", "", "")
	cmdFlags.IntVar(&delBroker, "delbroker", -1, "")
	cmdFlags.BoolVar(&this.registeredBrokers, "r", false, "")
	cmdFlags.BoolVar(&verifyMode, "verify", false, "")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if validateArgs(this, this.Ui).
		on("-add", "-z", "-p").
		on("-s", "-z", "-c").
		requireAdminRights("-s", "-add").
		invalid(args) {
		return 2
	}

	if addCluster != "" {
		// add cluster
		zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
		defer printSwallowedErrors(this.Ui, zkzone)

		if err := zkzone.RegisterCluster(addCluster, clusterPath); err != nil {
			this.Ui.Error(err.Error())
			return 1
		}

		this.Ui.Info(fmt.Sprintf("%s: %s created", addCluster, clusterPath))

		return
	}

	if setMode {
		// setup a cluser meta info
		zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
		zkcluster := zkzone.NewCluster(clusterName)
		switch {
		case priority != -1:
			zkcluster.SetPriority(priority)

		case replicas != -1:
			zkcluster.SetReplicas(replicas)

		case nickname != "":
			zkcluster.SetNickname(nickname)

		case addBroker != "":
			parts := strings.Split(addBroker, ":")
			if len(parts) != 3 {
				this.Ui.Output(this.Help())
				return
			}

			brokerId, err := strconv.Atoi(parts[0])
			swallow(err)
			port, err := strconv.Atoi(parts[2])
			swallow(err)
			err = zkcluster.RegisterBroker(brokerId, parts[1], port)
			swallow(err)

		case delBroker != -1:
			this.Ui.Error("not implemented yet")

		default:
			this.Ui.Error("command not recognized")
		}

		return
	}

	if verifyMode {
		if zone != "" {
			zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
			this.verifyBrokers(zkzone)

			printSwallowedErrors(this.Ui, zkzone)
		} else {
			// print all zones all clusters
			forSortedZones(func(zkzone *zk.ZkZone) {
				this.verifyBrokers(zkzone)

				printSwallowedErrors(this.Ui, zkzone)
			})
		}
		return
	}

	// display mode
	if zone != "" {
		zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
		this.printClusters(zkzone)

		printSwallowedErrors(this.Ui, zkzone)
	} else {
		// print all zones all clusters
		forSortedZones(func(zkzone *zk.ZkZone) {
			this.printClusters(zkzone)

			printSwallowedErrors(this.Ui, zkzone)
		})
	}

	return
}

func (this *Clusters) printRegisteredBrokers(zkzone *zk.ZkZone) {
	this.Ui.Output(zkzone.Name())
	zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
		info := zkcluster.RegisteredInfo()
		this.Ui.Output(fmt.Sprintf("    %s(%s)", info.Name(), info.Nickname))
		registeredBrokers := info.Roster
		if len(registeredBrokers) == 0 {
			this.Ui.Warn("        brokers not defined")
		} else {
			for _, b := range registeredBrokers {
				this.Ui.Output(fmt.Sprintf("        %2d %s", b.Id, b.Addr()))
			}
		}

	})
}

func (this *Clusters) verifyBrokers(zkzone *zk.ZkZone) {
	this.Ui.Output(zkzone.Name())
	zkzone.ForSortedBrokers(func(cluster string, liveBrokers map[string]*zk.BrokerZnode) {
		zkcluster := zkzone.NewCluster(cluster)
		registeredBrokers := zkcluster.RegisteredInfo().Roster

		// find diff between registeredBrokers and liveBrokers
		// loop1 find liveBrokers>registeredBrokers
		for _, broker := range liveBrokers {
			foundInRoster := false
			for _, b := range registeredBrokers {
				bid := strconv.Itoa(b.Id)
				if bid == broker.Id && broker.Addr() == b.Addr() {
					foundInRoster = true
					break
				}
			}

			if !foundInRoster {
				// should manually register the broker
				this.Ui.Output(strings.Repeat(" ", 4) +
					color.Green("+ gk clusters -z %s -s -c %s -addbroker %s:%s",
						zkzone.Name(), cluster, broker.Id, broker.Addr()))
			}
		}

		// loop2 find liveBrokers<registeredBrokers
		for _, b := range registeredBrokers {
			foundInLive := false
			for _, broker := range liveBrokers {
				bid := strconv.Itoa(b.Id)
				if bid == broker.Id && broker.Addr() == b.Addr() {
					foundInLive = true
					break
				}
			}

			if !foundInLive {
				// the broker is dead
				this.Ui.Output(strings.Repeat(" ", 4) +
					color.Red("broker %d %s is dead", b.Id, b.Addr()))
			}
		}
	})
}

func (this *Clusters) printClusters(zkzone *zk.ZkZone) {
	if this.registeredBrokers {
		this.printRegisteredBrokers(zkzone)
		return
	}

	type clusterInfo struct {
		name, path         string
		topicN, partitionN int
		err                string
		priority           int
		replicas           int
		brokerInfos        []zk.BrokerInfo
	}
	clusters := make([]clusterInfo, 0)
	zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
		ci := clusterInfo{
			name: zkcluster.Name(),
			path: zkcluster.Chroot(),
		}
		if !this.verbose {
			clusters = append(clusters, ci)
			return
		}

		// verbose mode, will calculate topics and partition count
		brokerList := zkcluster.BrokerList()
		if len(brokerList) == 0 {
			ci.err = "no live brokers"
			clusters = append(clusters, ci)
			return
		}

		kfk, err := sarama.NewClient(brokerList, sarama.NewConfig())
		if err != nil {
			ci.err = err.Error()
			clusters = append(clusters, ci)
			return
		}
		topics, err := kfk.Topics()
		if err != nil {
			ci.err = err.Error()
			clusters = append(clusters, ci)
			return
		}
		partitionN := 0
		for _, topic := range topics {
			partitions, err := kfk.Partitions(topic)
			if err != nil {
				ci.err = err.Error()
				clusters = append(clusters, ci)
				continue
			}

			partitionN += len(partitions)
		}

		info := zkcluster.RegisteredInfo()
		clusters = append(clusters, clusterInfo{
			name:        zkcluster.Name(),
			path:        zkcluster.Chroot(),
			topicN:      len(topics),
			partitionN:  partitionN,
			replicas:    info.Replicas,
			priority:    info.Priority,
			brokerInfos: info.Roster,
		})
	})

	this.Ui.Output(fmt.Sprintf("%s: %d", zkzone.Name(), len(clusters)))
	if this.verbose {
		// 2 loop: 1. print the err clusters 2. print the good clusters
		for _, c := range clusters {
			if c.err == "" {
				continue
			}

			this.Ui.Output(fmt.Sprintf("%30s: %s %s", c.name, c.path,
				color.Red(c.err)))
		}

		// loop2
		for _, c := range clusters {
			if c.err != "" {
				continue
			}

			this.Ui.Output(fmt.Sprintf("%30s: %s",
				c.name, c.path))
			this.Ui.Output(strings.Repeat(" ", 4) +
				color.Blue("topics:%d partitions:%d replicas:%d priority:%d brokers:%+v",
					c.topicN, c.partitionN, c.replicas, c.priority, c.brokerInfos))
		}

		return
	}

	// not verbose mode
	for _, c := range clusters {
		this.Ui.Output(fmt.Sprintf("%30s: %s", c.name, c.path))
	}

}

func (*Clusters) Synopsis() string {
	return "Register or display kafka clusters"
}

func (this *Clusters) Help() string {
	help := fmt.Sprintf(`
Usage: %s clusters [options]

    Register or display kafka clusters

Options:

    -z zone
      Only print kafka clusters within this zone.

    -c cluster name
      The new kafka cluster name.

    -l
      Use a long listing format.

    -add cluster name
      Add a new kafka cluster into a zone.

    -p cluster zk path
      The new kafka cluster chroot path in Zookeeper.
      e,g. gk clusters -z prod -add foo -p /kafka

    -s
      Setup a cluster info.

    -priority n
      Set the priority of a cluster.

    -nickname name
      Set nickname of a cluster.
      e,g. gk clusters -z prod -c foo -s -nickname bar

    -replicas n
      Set the default replicas of a cluster.

    -addbroker id:host:port
      Register a permanent broker to a cluster.

    -delbroker id TODO
      Delete a broker from a cluster.

    -r
      Display registered permanent brokers info.

    -verify
      Verify that the online brokers are consistent with the registered brokers.

`, this.Cmd)
	return strings.TrimSpace(help)
}
<commit_msg>display cluster nickname in verbose mode<commit_after>package command

import (
	"flag"
	"fmt"
	"strconv"
	"strings"

	"github.com/Shopify/sarama"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/gocli"
	"github.com/funkygao/golib/color"
)

type Clusters struct {
	Ui  cli.Ui
	Cmd string

	verbose           bool
	registeredBrokers bool
}

// TODO cluster info will contain desciption,owner,etc.
func (this *Clusters) Run(args []string) (exitCode int) {
	var (
		addCluster  string
		setMode     bool
		verifyMode  bool
		clusterName string
		clusterPath string
		zone        string
		priority    int
		replicas    int
		addBroker   string
		nickname    string
		delBroker   int
	)
	cmdFlags := flag.NewFlagSet("clusters", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&zone, "z", "", "")
	cmdFlags.StringVar(&addCluster, "add", "", "")
	cmdFlags.BoolVar(&setMode, "s", false, "")
	cmdFlags.StringVar(&clusterName, "c", "", "")
	cmdFlags.StringVar(&clusterPath, "p", "", "")
	cmdFlags.BoolVar(&this.verbose, "l", false, "")
	cmdFlags.IntVar(&replicas, "replicas", -1, "")
	cmdFlags.IntVar(&priority, "priority", -1, "")
	cmdFlags.StringVar(&addBroker, "addbroker", "", "")
	cmdFlags.StringVar(&nickname, "nickname", "", "")
	cmdFlags.IntVar(&delBroker, "delbroker", -1, "")
	cmdFlags.BoolVar(&this.registeredBrokers, "r", false, "")
	cmdFlags.BoolVar(&verifyMode, "verify", false, "")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if validateArgs(this, this.Ui).
		on("-add", "-z", "-p").
		on("-s", "-z", "-c").
		requireAdminRights("-s", "-add").
		invalid(args) {
		return 2
	}

	if addCluster != "" {
		// add cluster
		zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
		defer printSwallowedErrors(this.Ui, zkzone)

		if err := zkzone.RegisterCluster(addCluster, clusterPath); err != nil {
			this.Ui.Error(err.Error())
			return 1
		}

		this.Ui.Info(fmt.Sprintf("%s: %s created", addCluster, clusterPath))

		return
	}

	if setMode {
		// setup a cluser meta info
		zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
		zkcluster := zkzone.NewCluster(clusterName)
		switch {
		case priority != -1:
			zkcluster.SetPriority(priority)

		case replicas != -1:
			zkcluster.SetReplicas(replicas)

		case nickname != "":
			zkcluster.SetNickname(nickname)

		case addBroker != "":
			parts := strings.Split(addBroker, ":")
			if len(parts) != 3 {
				this.Ui.Output(this.Help())
				return
			}

			brokerId, err := strconv.Atoi(parts[0])
			swallow(err)
			port, err := strconv.Atoi(parts[2])
			swallow(err)
			err = zkcluster.RegisterBroker(brokerId, parts[1], port)
			swallow(err)

		case delBroker != -1:
			this.Ui.Error("not implemented yet")

		default:
			this.Ui.Error("command not recognized")
		}

		return
	}

	if verifyMode {
		if zone != "" {
			zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
			this.verifyBrokers(zkzone)

			printSwallowedErrors(this.Ui, zkzone)
		} else {
			// print all zones all clusters
			forSortedZones(func(zkzone *zk.ZkZone) {
				this.verifyBrokers(zkzone)

				printSwallowedErrors(this.Ui, zkzone)
			})
		}
		return
	}

	// display mode
	if zone != "" {
		zkzone := zk.NewZkZone(zk.DefaultConfig(zone, ctx.ZoneZkAddrs(zone)))
		this.printClusters(zkzone)

		printSwallowedErrors(this.Ui, zkzone)
	} else {
		// print all zones all clusters
		forSortedZones(func(zkzone *zk.ZkZone) {
			this.printClusters(zkzone)

			printSwallowedErrors(this.Ui, zkzone)
		})
	}

	return
}

func (this *Clusters) printRegisteredBrokers(zkzone *zk.ZkZone) {
	this.Ui.Output(zkzone.Name())
	zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
		info := zkcluster.RegisteredInfo()
		this.Ui.Output(fmt.Sprintf("    %s(%s)", info.Name(), info.Nickname))
		registeredBrokers := info.Roster
		if len(registeredBrokers) == 0 {
			this.Ui.Warn("        brokers not defined")
		} else {
			for _, b := range registeredBrokers {
				this.Ui.Output(fmt.Sprintf("        %2d %s", b.Id, b.Addr()))
			}
		}

	})
}

func (this *Clusters) verifyBrokers(zkzone *zk.ZkZone) {
	this.Ui.Output(zkzone.Name())
	zkzone.ForSortedBrokers(func(cluster string, liveBrokers map[string]*zk.BrokerZnode) {
		zkcluster := zkzone.NewCluster(cluster)
		registeredBrokers := zkcluster.RegisteredInfo().Roster

		// find diff between registeredBrokers and liveBrokers
		// loop1 find liveBrokers>registeredBrokers
		for _, broker := range liveBrokers {
			foundInRoster := false
			for _, b := range registeredBrokers {
				bid := strconv.Itoa(b.Id)
				if bid == broker.Id && broker.Addr() == b.Addr() {
					foundInRoster = true
					break
				}
			}

			if !foundInRoster {
				// should manually register the broker
				this.Ui.Output(strings.Repeat(" ", 4) +
					color.Green("+ gk clusters -z %s -s -c %s -addbroker %s:%s",
						zkzone.Name(), cluster, broker.Id, broker.Addr()))
			}
		}

		// loop2 find liveBrokers<registeredBrokers
		for _, b := range registeredBrokers {
			foundInLive := false
			for _, broker := range liveBrokers {
				bid := strconv.Itoa(b.Id)
				if bid == broker.Id && broker.Addr() == b.Addr() {
					foundInLive = true
					break
				}
			}

			if !foundInLive {
				// the broker is dead
				this.Ui.Output(strings.Repeat(" ", 4) +
					color.Red("broker %d %s is dead", b.Id, b.Addr()))
			}
		}
	})
}

func (this *Clusters) printClusters(zkzone *zk.ZkZone) {
	if this.registeredBrokers {
		this.printRegisteredBrokers(zkzone)
		return
	}

	type clusterInfo struct {
		name, path         string
		nickname           string
		topicN, partitionN int
		err                string
		priority           int
		replicas           int
		brokerInfos        []zk.BrokerInfo
	}
	clusters := make([]clusterInfo, 0)
	zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
		ci := clusterInfo{
			name: zkcluster.Name(),
			path: zkcluster.Chroot(),
		}
		if !this.verbose {
			clusters = append(clusters, ci)
			return
		}

		// verbose mode, will calculate topics and partition count
		brokerList := zkcluster.BrokerList()
		if len(brokerList) == 0 {
			ci.err = "no live brokers"
			clusters = append(clusters, ci)
			return
		}

		kfk, err := sarama.NewClient(brokerList, sarama.NewConfig())
		if err != nil {
			ci.err = err.Error()
			clusters = append(clusters, ci)
			return
		}
		topics, err := kfk.Topics()
		if err != nil {
			ci.err = err.Error()
			clusters = append(clusters, ci)
			return
		}
		partitionN := 0
		for _, topic := range topics {
			partitions, err := kfk.Partitions(topic)
			if err != nil {
				ci.err = err.Error()
				clusters = append(clusters, ci)
				continue
			}

			partitionN += len(partitions)
		}

		info := zkcluster.RegisteredInfo()
		clusters = append(clusters, clusterInfo{
			name:        zkcluster.Name(),
			nickname:    info.Nickname,
			path:        zkcluster.Chroot(),
			topicN:      len(topics),
			partitionN:  partitionN,
			replicas:    info.Replicas,
			priority:    info.Priority,
			brokerInfos: info.Roster,
		})
	})

	this.Ui.Output(fmt.Sprintf("%s: %d", zkzone.Name(), len(clusters)))
	if this.verbose {
		// 2 loop: 1. print the err clusters 2. print the good clusters
		for _, c := range clusters {
			if c.err == "" {
				continue
			}

			this.Ui.Output(fmt.Sprintf("%30s: %s %s", c.name, c.path,
				color.Red(c.err)))
		}

		// loop2
		for _, c := range clusters {
			if c.err != "" {
				continue
			}

			this.Ui.Output(fmt.Sprintf("%30s: %s",
				c.name, c.path))
			this.Ui.Output(strings.Repeat(" ", 4) +
				color.Blue("nick:%s topics:%d partitions:%d replicas:%d priority:%d brokers:%+v",
					c.nickname,
					c.topicN, c.partitionN, c.replicas, c.priority, c.brokerInfos))
		}

		return
	}

	// not verbose mode
	for _, c := range clusters {
		this.Ui.Output(fmt.Sprintf("%30s: %s", c.name, c.path))
	}

}

func (*Clusters) Synopsis() string {
	return "Register or display kafka clusters"
}

func (this *Clusters) Help() string {
	help := fmt.Sprintf(`
Usage: %s clusters [options]

    Register or display kafka clusters

Options:

    -z zone
      Only print kafka clusters within this zone.

    -c cluster name
      The new kafka cluster name.

    -l
      Use a long listing format.

    -add cluster name
      Add a new kafka cluster into a zone.

    -p cluster zk path
      The new kafka cluster chroot path in Zookeeper.
      e,g. gk clusters -z prod -add foo -p /kafka

    -s
      Setup a cluster info.

    -priority n
      Set the priority of a cluster.

    -nickname name
      Set nickname of a cluster.
      e,g. gk clusters -z prod -c foo -s -nickname bar

    -replicas n
      Set the default replicas of a cluster.

    -addbroker id:host:port
      Register a permanent broker to a cluster.

    -delbroker id TODO
      Delete a broker from a cluster.

    -r
      Display registered permanent brokers info.

    -verify
      Verify that the online brokers are consistent with the registered brokers.

`, this.Cmd)
	return strings.TrimSpace(help)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package app

import (
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"github.com/golang/glog"
	"github.com/skynetservices/skydns/metrics"
	"github.com/skynetservices/skydns/server"
	"github.com/spf13/pflag"

	"k8s.io/kubernetes/cmd/kube-dns/app/options"
	"k8s.io/kubernetes/pkg/api/unversioned"
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
	"k8s.io/kubernetes/pkg/client/restclient"
	kclientcmd "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	kdns "k8s.io/kubernetes/pkg/dns"
	"k8s.io/kubernetes/pkg/version"
)

type KubeDNSServer struct {
	// DNS domain name.
	domain      string
	healthzPort int
	dnsPort     int
	kd          *kdns.KubeDNS
}

func NewKubeDNSServerDefault(config *options.KubeDNSConfig) *KubeDNSServer {
	ks := KubeDNSServer{
		domain: config.ClusterDomain,
	}

	kubeClient, err := newKubeClient(config)
	if err != nil {
		glog.Fatalf("Failed to create a kubernetes client: %v", err)
	}
	ks.healthzPort = config.HealthzPort
	ks.dnsPort = config.DNSPort
	ks.kd, err = kdns.NewKubeDNS(kubeClient, config.ClusterDomain, config.Federations)
	if err != nil {
		glog.Fatalf("Failed to start kubeDNS: %v", err)
	}
	return &ks
}

// TODO: evaluate using pkg/client/clientcmd
func newKubeClient(dnsConfig *options.KubeDNSConfig) (clientset.Interface, error) {
	var (
		config *restclient.Config
		err    error
	)

	if dnsConfig.KubeMasterURL != "" && dnsConfig.KubeConfigFile == "" {
		// Only --kube-master-url was provided.
		config = &restclient.Config{
			Host:          dnsConfig.KubeMasterURL,
			ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}},
		}
	} else {
		// We either have:
		//  1) --kube-master-url and --kubecfg-file
		//  2) just --kubecfg-file
		//  3) neither flag
		// In any case, the logic is the same.  If (3), this will automatically
		// fall back on the service account token.
		overrides := &kclientcmd.ConfigOverrides{}
		overrides.ClusterInfo.Server = dnsConfig.KubeMasterURL                                // might be "", but that is OK
		rules := &kclientcmd.ClientConfigLoadingRules{ExplicitPath: dnsConfig.KubeConfigFile} // might be "", but that is OK
		if config, err = kclientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig(); err != nil {
			return nil, err
		}
	}

	glog.Infof("Using %s for kubernetes master, kubernetes API: %v", config.Host, config.GroupVersion)
	return clientset.NewForConfig(config)
}

func (server *KubeDNSServer) Run() {
	glog.Infof("%+v", version.Get())
	pflag.VisitAll(func(flag *pflag.Flag) {
		glog.Infof("FLAG: --%s=%q", flag.Name, flag.Value)
	})
	setupSignalHandlers()
	server.startSkyDNSServer()
	server.kd.Start()
	server.setupHealthzHandlers()
	glog.Infof("Setting up Healthz Handler(/readiness, /cache) on port :%d", server.healthzPort)
	glog.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", server.healthzPort), nil))
}

// setupHealthzHandlers sets up a readiness and liveness endpoint for kube2sky.
func (server *KubeDNSServer) setupHealthzHandlers() {
	http.HandleFunc("/readiness", func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, "ok\n")
	})
	http.HandleFunc("/cache", func(w http.ResponseWriter, req *http.Request) {
		serializedJSON, err := server.kd.GetCacheAsJSON()
		if err == nil {
			fmt.Fprint(w, serializedJSON)
		} else {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprint(w, err)
		}
	})
}

// setupSignalHandlers runs a goroutine that waits on SIGINT or SIGTERM and logs it
// before exiting.
func setupSignalHandlers() {
	sigChan := make(chan os.Signal)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		glog.Fatalf("Received signal: %s", <-sigChan)
	}()
}

func (d *KubeDNSServer) startSkyDNSServer() {
	glog.Infof("Starting SkyDNS server. Listening on port:%d", d.dnsPort)
	skydnsConfig := &server.Config{Domain: d.domain, DnsAddr: fmt.Sprintf("0.0.0.0:%d", d.dnsPort)}
	server.SetDefaults(skydnsConfig)
	s := server.New(d.kd, skydnsConfig)
	if err := metrics.Metrics(); err != nil {
		glog.Fatalf("skydns: %s", err)
	}
	glog.Infof("skydns: metrics enabled on : %s:%s", metrics.Path, metrics.Port)

	go s.Run()
}
<commit_msg>Support graceful termination in kube-dns<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package app

import (
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"github.com/golang/glog"
	"github.com/skynetservices/skydns/metrics"
	"github.com/skynetservices/skydns/server"
	"github.com/spf13/pflag"

	"k8s.io/kubernetes/cmd/kube-dns/app/options"
	"k8s.io/kubernetes/pkg/api/unversioned"
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
	"k8s.io/kubernetes/pkg/client/restclient"
	kclientcmd "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	kdns "k8s.io/kubernetes/pkg/dns"
	"k8s.io/kubernetes/pkg/version"
)

type KubeDNSServer struct {
	// DNS domain name.
	domain      string
	healthzPort int
	dnsPort     int
	kd          *kdns.KubeDNS
}

func NewKubeDNSServerDefault(config *options.KubeDNSConfig) *KubeDNSServer {
	ks := KubeDNSServer{
		domain: config.ClusterDomain,
	}

	kubeClient, err := newKubeClient(config)
	if err != nil {
		glog.Fatalf("Failed to create a kubernetes client: %v", err)
	}
	ks.healthzPort = config.HealthzPort
	ks.dnsPort = config.DNSPort
	ks.kd, err = kdns.NewKubeDNS(kubeClient, config.ClusterDomain, config.Federations)
	if err != nil {
		glog.Fatalf("Failed to start kubeDNS: %v", err)
	}
	return &ks
}

// TODO: evaluate using pkg/client/clientcmd
func newKubeClient(dnsConfig *options.KubeDNSConfig) (clientset.Interface, error) {
	var (
		config *restclient.Config
		err    error
	)

	if dnsConfig.KubeMasterURL != "" && dnsConfig.KubeConfigFile == "" {
		// Only --kube-master-url was provided.
		config = &restclient.Config{
			Host:          dnsConfig.KubeMasterURL,
			ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}},
		}
	} else {
		// We either have:
		//  1) --kube-master-url and --kubecfg-file
		//  2) just --kubecfg-file
		//  3) neither flag
		// In any case, the logic is the same.  If (3), this will automatically
		// fall back on the service account token.
		overrides := &kclientcmd.ConfigOverrides{}
		overrides.ClusterInfo.Server = dnsConfig.KubeMasterURL                                // might be "", but that is OK
		rules := &kclientcmd.ClientConfigLoadingRules{ExplicitPath: dnsConfig.KubeConfigFile} // might be "", but that is OK
		if config, err = kclientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig(); err != nil {
			return nil, err
		}
	}

	glog.Infof("Using %s for kubernetes master, kubernetes API: %v", config.Host, config.GroupVersion)
	return clientset.NewForConfig(config)
}

func (server *KubeDNSServer) Run() {
	glog.Infof("%+v", version.Get())
	pflag.VisitAll(func(flag *pflag.Flag) {
		glog.Infof("FLAG: --%s=%q", flag.Name, flag.Value)
	})
	setupSignalHandlers()
	server.startSkyDNSServer()
	server.kd.Start()
	server.setupHealthzHandlers()
	glog.Infof("Setting up Healthz Handler(/readiness, /cache) on port :%d", server.healthzPort)
	glog.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", server.healthzPort), nil))
}

// setupHealthzHandlers sets up a readiness and liveness endpoint for kube2sky.
func (server *KubeDNSServer) setupHealthzHandlers() {
	http.HandleFunc("/readiness", func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, "ok\n")
	})
	http.HandleFunc("/cache", func(w http.ResponseWriter, req *http.Request) {
		serializedJSON, err := server.kd.GetCacheAsJSON()
		if err == nil {
			fmt.Fprint(w, serializedJSON)
		} else {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprint(w, err)
		}
	})
}

// setupSignalHandlers runs a goroutine that waits on SIGINT or SIGTERM and logs it
// program will be terminated by SIGKILL when grace period ends.
func setupSignalHandlers() {
	sigChan := make(chan os.Signal)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		glog.Infof("Received signal: %s, will exit when the grace period ends", <-sigChan)
	}()
}

func (d *KubeDNSServer) startSkyDNSServer() {
	glog.Infof("Starting SkyDNS server. Listening on port:%d", d.dnsPort)
	skydnsConfig := &server.Config{Domain: d.domain, DnsAddr: fmt.Sprintf("0.0.0.0:%d", d.dnsPort)}
	server.SetDefaults(skydnsConfig)
	s := server.New(d.kd, skydnsConfig)
	if err := metrics.Metrics(); err != nil {
		glog.Fatalf("skydns: %s", err)
	}
	glog.Infof("skydns: metrics enabled on : %s:%s", metrics.Path, metrics.Port)

	go s.Run()
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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

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

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

package cmd

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
	cmdUtil "k8s.io/minikube/cmd/util"
	"k8s.io/minikube/pkg/minikube/cluster"
	"k8s.io/minikube/pkg/minikube/machine"
)

// deleteCmd represents the delete command
var deleteCmd = &cobra.Command{
	Use:   "delete",
	Short: "Deletes a local kubernetes cluster.",
	Long: `Deletes a local kubernetes cluster. This command deletes the VM, and removes all
associated files.`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Deleting local Kubernetes cluster...")
		api, err := machine.NewAPIClient(clientType)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
			os.Exit(1)
		}
		defer api.Close()

		if err = cluster.DeleteHost(api); err != nil {
			fmt.Println("Errors occurred deleting machine: ", err)
			cmdUtil.MaybeReportErrorAndExit(err)
		}
		fmt.Println("Machine deleted.")
	},
}

func init() {
	RootCmd.AddCommand(deleteCmd)
}
<commit_msg>Removed error reporting prompt from minikube delete<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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

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

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

package cmd

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
	"k8s.io/minikube/pkg/minikube/cluster"
	"k8s.io/minikube/pkg/minikube/machine"
)

// deleteCmd represents the delete command
var deleteCmd = &cobra.Command{
	Use:   "delete",
	Short: "Deletes a local kubernetes cluster.",
	Long: `Deletes a local kubernetes cluster. This command deletes the VM, and removes all
associated files.`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Deleting local Kubernetes cluster...")
		api, err := machine.NewAPIClient(clientType)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
			os.Exit(1)
		}
		defer api.Close()

		if err = cluster.DeleteHost(api); err != nil {
			fmt.Println("Errors occurred deleting machine: ", err)
			os.Exit(1)
		}
		fmt.Println("Machine deleted.")
	},
}

func init() {
	RootCmd.AddCommand(deleteCmd)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/labstack/gommon/log"
	"github.com/scritch007/go-moviename"
)

var debug bool

func init() {
	flag.BoolVar(&debug, "v", false, "Enable debug logs")
}

func main() {
	flag.Parse()
	logger := log.New("cmdLine")
	if debug {
		logger.SetLevel(log.DEBUG)
	}
	mp := moviename.NewMovieParser(logger)
	if len(flag.Args()) != 1 {
		fmt.Printf("Usage: %s filename", os.Args[0])
		os.Exit(1)
	}
	m, err := mp.Parse(flag.Args()[0])
	if err != nil {
		fmt.Printf("%v", err)
		os.Exit(1)
	}
	fmt.Printf("%s (%d) => %s\n", m.Name, m.Year, m.Quality)
}
<commit_msg>Rename to new repo name<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/labstack/gommon/log"
	"github.com/scritch007/go-medianame"
)

var debug bool

func init() {
	flag.BoolVar(&debug, "v", false, "Enable debug logs")
}

func main() {
	flag.Parse()
	logger := log.New("cmdLine")
	if debug {
		logger.SetLevel(log.DEBUG)
	}
	mp := moviename.NewMovieParser(logger)
	if len(flag.Args()) != 1 {
		fmt.Printf("Usage: %s filename", os.Args[0])
		os.Exit(1)
	}
	m, err := mp.Parse(flag.Args()[0])
	if err != nil {
		fmt.Printf("%v", err)
		os.Exit(1)
	}
	fmt.Printf("%s (%d) => %s\n", m.Name, m.Year, m.Quality)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"

	"github.com/mitchellh/cli"
)

// a list of generators for all the subcommand types
var subCommandFactory = map[string]cli.CommandFactory{
	"list": func() (cli.Command, error) {
		return &listCommand{}, nil
	},
	"test": func() (cli.Command, error) {
		return &testCommand{}, nil
	},
	"run": func() (cli.Command, error) {
		return &runCommand{}, nil
	},
	"eval": func() (cli.Command, error) {
		return &evalCommand{}, nil
	},
}

// listCommand loads the config, and lists the configured nodes
type listCommand struct {
	configFilename string
}

func (c *listCommand) Synopsis() string {
	return "list all configured nodes"
}

func (c *listCommand) Help() string {
	return `Usage: trasporter list --config [file]

   list the nodes that have been configured in the configuration yaml`
}

func (c *listCommand) Run(args []string) int {
	var configFilename string
	cmdFlags := flag.NewFlagSet("list", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Help() }
	cmdFlags.StringVar(&configFilename, "config", "config.yaml", "config file")
	cmdFlags.Parse(args)

	config, err := LoadConfig(configFilename)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	for n, v := range config.Nodes {
		fmt.Println(n, v)
	}

	return 0
}

// runCommand loads a js file, and compiles and runs a
// javascript pipeline defined therein
type runCommand struct {
}

func newRunCommand() (cli.Command, error) {
	return &runCommand{}, nil
}

func (c *runCommand) Help() string {
	return `Usage: transporter run [--config file] <filename>

Run a transporter transporter application by sourcing a file containing the javascript application
and compiling the transporter pipeline`
}

func (c *runCommand) Synopsis() string {
	return "Run a transporter application loaded from a file"
}

func (c *runCommand) Run(args []string) int {
	var configFilename string
	cmdFlags := flag.NewFlagSet("run", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Help() }
	cmdFlags.StringVar(&configFilename, "config", "config.yaml", "config file")
	cmdFlags.Parse(args)

	config, err := LoadConfig(configFilename)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	if len(cmdFlags.Args()) == 0 {
		fmt.Println("Error: A name of a file to run is required")
		return 1
	}

	builder, err := NewJavascriptBuilder(config, cmdFlags.Args()[0], "")
	if err != nil {
		fmt.Println(err)
		return 1
	}
	if err = builder.Build(); err != nil {
		fmt.Println(err)
		return 1
	}

	if err = builder.Run(); err != nil {
		fmt.Println(err)
		return 1
	}
	return 0
}

// runCommand loads a js file, and compiles and runs a
// javascript pipeline defined therein
type testCommand struct {
}

func (c *testCommand) Help() string {
	return `Usage: transporter test [--config file]  <filename>

Compile a transporter application by sourcing an application file, but do not run it`
}

func (c *testCommand) Synopsis() string {
	return "display the compiled nodes without starting a pipeline"
}

func (c *testCommand) Run(args []string) int {
	var configFilename string
	cmdFlags := flag.NewFlagSet("test", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Help() }
	cmdFlags.StringVar(&configFilename, "config", "config.yaml", "config file")
	cmdFlags.Parse(args)

	config, err := LoadConfig(configFilename)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	if len(cmdFlags.Args()) == 0 {
		fmt.Println("Error: A name of a file to test is required")
		return 1
	}

	builder, err := NewJavascriptBuilder(config, cmdFlags.Args()[0], "")
	if err != nil {
		fmt.Println(err)
		return 1
	}
	if err = builder.Build(); err != nil {
		fmt.Println(err)
		return 1
	}
	fmt.Println(builder)
	return 0
}

// evalCommand compiles inline javascript into a transporter pipeline,
// and runs it
type evalCommand struct {
}

func (c *evalCommand) Help() string {
	return `Usage: transporter eval [--config file]  <javascript>

Compile a transporter application by evaluating the given javascript`
}

func (c *evalCommand) Synopsis() string {
	return "Eval javascript to build and run a transporter application"
}

func (c *evalCommand) Run(args []string) int {
	var configFilename string
	cmdFlags := flag.NewFlagSet("run", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Help() }
	cmdFlags.StringVar(&configFilename, "config", "config.yaml", "config file")
	cmdFlags.Parse(args)

	config, err := LoadConfig(configFilename)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	if len(cmdFlags.Args()) == 0 {
		fmt.Println("Error: A string to evaluate is required")
		return 1
	}

	builder, err := NewJavascriptBuilder(config, "", cmdFlags.Args()[0])
	if err != nil {
		fmt.Println(err)
		return 1
	}
	if err = builder.Build(); err != nil {
		fmt.Println(err)
		return 1
	}

	if err = builder.Run(); err != nil {
		fmt.Println(err)
		return 1
	}

	return 0
}
<commit_msg>Pretty print the list<commit_after>package main

import (
	"flag"
	"fmt"

	"github.com/mitchellh/cli"
)

// a list of generators for all the subcommand types
var subCommandFactory = map[string]cli.CommandFactory{
	"list": func() (cli.Command, error) {
		return &listCommand{}, nil
	},
	"test": func() (cli.Command, error) {
		return &testCommand{}, nil
	},
	"run": func() (cli.Command, error) {
		return &runCommand{}, nil
	},
	"eval": func() (cli.Command, error) {
		return &evalCommand{}, nil
	},
}

// listCommand loads the config, and lists the configured nodes
type listCommand struct {
	configFilename string
}

func (c *listCommand) Synopsis() string {
	return "list all configured nodes"
}

func (c *listCommand) Help() string {
	return `Usage: trasporter list --config [file]

   list the nodes that have been configured in the configuration yaml`
}

func (c *listCommand) Run(args []string) int {
	var configFilename string
	cmdFlags := flag.NewFlagSet("list", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Help() }
	cmdFlags.StringVar(&configFilename, "config", "config.yaml", "config file")
	cmdFlags.Parse(args)

	config, err := LoadConfig(configFilename)
	if err != nil {
		fmt.Println(err)
		return 1
	}
	fmt.Printf("%-20s %-15s %s\n", "Name", "Type", "URI")
	for n, v := range config.Nodes {
		fmt.Printf("%-20s %-15s %s\n", n, v.Type, v.URI)
	}

	return 0
}

// runCommand loads a js file, and compiles and runs a
// javascript pipeline defined therein
type runCommand struct {
}

func newRunCommand() (cli.Command, error) {
	return &runCommand{}, nil
}

func (c *runCommand) Help() string {
	return `Usage: transporter run [--config file] <filename>

Run a transporter transporter application by sourcing a file containing the javascript application
and compiling the transporter pipeline`
}

func (c *runCommand) Synopsis() string {
	return "Run a transporter application loaded from a file"
}

func (c *runCommand) Run(args []string) int {
	var configFilename string
	cmdFlags := flag.NewFlagSet("run", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Help() }
	cmdFlags.StringVar(&configFilename, "config", "config.yaml", "config file")
	cmdFlags.Parse(args)

	config, err := LoadConfig(configFilename)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	if len(cmdFlags.Args()) == 0 {
		fmt.Println("Error: A name of a file to run is required")
		return 1
	}

	builder, err := NewJavascriptBuilder(config, cmdFlags.Args()[0], "")
	if err != nil {
		fmt.Println(err)
		return 1
	}
	if err = builder.Build(); err != nil {
		fmt.Println(err)
		return 1
	}

	if err = builder.Run(); err != nil {
		fmt.Println(err)
		return 1
	}
	return 0
}

// runCommand loads a js file, and compiles and runs a
// javascript pipeline defined therein
type testCommand struct {
}

func (c *testCommand) Help() string {
	return `Usage: transporter test [--config file]  <filename>

Compile a transporter application by sourcing an application file, but do not run it`
}

func (c *testCommand) Synopsis() string {
	return "display the compiled nodes without starting a pipeline"
}

func (c *testCommand) Run(args []string) int {
	var configFilename string
	cmdFlags := flag.NewFlagSet("test", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Help() }
	cmdFlags.StringVar(&configFilename, "config", "config.yaml", "config file")
	cmdFlags.Parse(args)

	config, err := LoadConfig(configFilename)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	if len(cmdFlags.Args()) == 0 {
		fmt.Println("Error: A name of a file to test is required")
		return 1
	}

	builder, err := NewJavascriptBuilder(config, cmdFlags.Args()[0], "")
	if err != nil {
		fmt.Println(err)
		return 1
	}
	if err = builder.Build(); err != nil {
		fmt.Println(err)
		return 1
	}
	fmt.Println(builder)
	return 0
}

// evalCommand compiles inline javascript into a transporter pipeline,
// and runs it
type evalCommand struct {
}

func (c *evalCommand) Help() string {
	return `Usage: transporter eval [--config file]  <javascript>

Compile a transporter application by evaluating the given javascript`
}

func (c *evalCommand) Synopsis() string {
	return "Eval javascript to build and run a transporter application"
}

func (c *evalCommand) Run(args []string) int {
	var configFilename string
	cmdFlags := flag.NewFlagSet("run", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Help() }
	cmdFlags.StringVar(&configFilename, "config", "config.yaml", "config file")
	cmdFlags.Parse(args)

	config, err := LoadConfig(configFilename)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	if len(cmdFlags.Args()) == 0 {
		fmt.Println("Error: A string to evaluate is required")
		return 1
	}

	builder, err := NewJavascriptBuilder(config, "", cmdFlags.Args()[0])
	if err != nil {
		fmt.Println(err)
		return 1
	}
	if err = builder.Build(); err != nil {
		fmt.Println(err)
		return 1
	}

	if err = builder.Run(); err != nil {
		fmt.Println(err)
		return 1
	}

	return 0
}
<|endoftext|>