<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/martini"
	"io/ioutil"
	"math/rand"
	"encoding/json"
)

func main() {
    m := martini.Classic()

    file, e := ioutil.ReadFile("./puns.json")
    if e != nil {
        fmt.Printf("File error: %v\n", e)
    }
    fmt.Printf("%s\n", string(file))

    var jsontype jsonobject
    json.Unmarshal(file, &jsontype)
    fmt.Printf("Results: %v\n", jsontype)

    m.Get("/api/random", func() string {
        return "test"
    })

    m.Run()
}
<commit_msg>add app.go<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/martini"
	"io/ioutil"
	"math/rand"
	"encoding/json"
)

func main() {
    m := martini.Classic()

    type jsonobject struct {
    Object ObjectType
    }

    file, e := ioutil.ReadFile("./puns.json")
    if e != nil {
        fmt.Printf("File error: %v\n", e)
    }
    fmt.Printf("%s\n", string(file))

    var jsontype jsonobject
    json.Unmarshal(file, &jsontype)
    fmt.Printf("Results: %v\n", jsontype)

    s1 := rand.NewSource(42)
    r1 := rand.New(s1)
    fmt.Print(r1.Intn(100))

    m.Get("/api/random", func() string {
        return "test"
    })

    m.Run()
}
<|endoftext|>


<commit_before>// Summary: Application code for Blockfreight™ | The blockchain of global freight.
// License: MIT License
// Company: Blockfreight, Inc.
// Author: Julian Nunez, Neil Tran, Julian Smith, Gian Felipe & contributors
// Site: https://blockfreight.com
// Support: <support@blockfreight.com>

// Copyright © 2017 Blockfreight, Inc. All Rights Reserved.

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// =================================================================================================================================================
// =================================================================================================================================================
//
// BBBBBBBBBBBb     lll                                kkk             ffff                         iii                  hhh            ttt
// BBBB``````BBBB   lll                                kkk            fff                           ```                  hhh            ttt
// BBBB      BBBB   lll      oooooo        ccccccc     kkk    kkkk  fffffff  rrr  rrr    eeeee      iii     gggggg ggg   hhh  hhhhh   tttttttt
// BBBBBBBBBBBB     lll    ooo    oooo    ccc    ccc   kkk   kkk    fffffff  rrrrrrrr eee    eeee   iii   gggg   ggggg   hhhh   hhhh  tttttttt
// BBBBBBBBBBBBBB   lll   ooo      ooo   ccc           kkkkkkk        fff    rrrr    eeeeeeeeeeeee  iii  gggg      ggg   hhh     hhh    ttt
// BBBB       BBB   lll   ooo      ooo   ccc           kkkk kkkk      fff    rrr     eeeeeeeeeeeee  iii   ggg      ggg   hhh     hhh    ttt
// BBBB      BBBB   lll   oooo    oooo   cccc    ccc   kkk   kkkk     fff    rrr      eee      eee  iii    ggg    gggg   hhh     hhh    tttt    ....
// BBBBBBBBBBBBB    lll     oooooooo       ccccccc     kkk     kkkk   fff    rrr       eeeeeeeee    iii     gggggg ggg   hhh     hhh     ttttt  ....
//                                                                                ggg      ggg
//   Blockfreight™ | The blockchain of global freight.                                                      ggggggggg
//
// =================================================================================================================================================
// =================================================================================================================================================

// Starts the Blockfreight™ Node to listen to all requests in the Blockfreight Network.
package main

import (
	// =======================
	// Golang Standard library
	// =======================
	"flag" // Implements command-line flag parsing.
	"fmt"  // Implements formatted I/O with functions analogous to C's printf and scanf.
	"log"  // Implements a simple logging package.
	"os"
	"strings"

	// ===============
	// Tendermint Core
	// ===============
	"github.com/tendermint/abci/client"
	"github.com/tendermint/abci/server"
	"github.com/tendermint/abci/types"
	"github.com/tendermint/abci/version"
	tendermint "github.com/tendermint/go-common"
	"github.com/urfave/cli"

	// ======================
	// Blockfreight™ packages
	// ======================
	"github.com/blockfreight/blockfreight-alpha/lib/app/bft" // Implements the main functions to work with the Blockfreight™ Network.
	"github.com/blockfreight/blockfreight-alpha/lib/pkg/key"
)

// Structure for data passed to print response.
type response struct {
	// generic abci response
	Data   []byte
	Code   types.CodeType
	Log    string
	Result string //Blockfreight Purposes
}

// client is a global variable so it can be reused by the console
var client abcicli.Client

func main() {

	//workaround for the cli library (https://github.com/urfave/cli/issues/565)
	cli.OsExiter = func(_ int) {}

	app := cli.NewApp()
	app.Name = "bftnode"
	app.Usage = "bftnode [command] [args...]"
	app.Version = version.Version
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "address",
			Value: "tcp://127.0.0.1:46658",
			//Value: "tcp://172.17.0.3:46658",
			Usage: "address of application socket",
		},
		cli.StringFlag{
			Name:  "call",
			Value: "socket",
			Usage: "socket or grpc",
		},
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "print the command and results as if it were a console session",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "start",
			Usage: "Start Blockfreight Node Application. (Parameters: none)",
			Action: func(c *cli.Context) {
				cmdStartServer()
			},
		},
		{
			Name:  "exit",
			Usage: "Leaves the program. (Parameters: none)",
			Action: func(c *cli.Context) {
				os.Exit(0)
			},
		},
		{
			Name:  "new_key",
			Usage: "Generate a new Public/Private Key",
			Action: func(c *cli.Context) error {
				return cmdGenerateKey(c)
			},
		},
	}
	err := app.Run(os.Args)
	if err != nil {
		log.Fatal(err.Error())
	}

}

// cmdGenerateKey function creates a new public/private key
func cmdGenerateKey(c *cli.Context) error {
	result, err := key.GenerateNewKey()
	if err != nil {
		return nil
	}

	printResponse(c, response{
		Result: result,
	})
	return nil
}

// cmdStartServer function creates the Blockfreight Node Application
func cmdStartServer() {

	fmt.Println("\n...........................................")
	fmt.Println("Blockfreight™ Node")
	fmt.Println("...........................................\n")

	// Parameters
	addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address")
	abciPtr := flag.String("bft", "socket", "socket | grpc")
	// persistencePtr := flag.String("persist", "", "directory to use for a database")
	flag.Parse()

	// Create the application - in memory or persisted to disk
	var app types.Application
	app = bft.NewBftApplication() //if *persistencePtr != "" => NewPersistentBftApplication(*persistencePtr)

	// Start the listener
	srv, err := server.NewServer(*addrPtr, *abciPtr, app)
	fmt.Println(srv)
	if err != nil {
		log.Fatal(err.Error())
	}
	fmt.Println("Service created by " + *abciPtr + " server")

	// Wait forever
	tendermint.TrapSignal(func() {
		// Cleanup
		fmt.Println("Stopping service")
		srv.Stop()
	})

}

func printResponse(c *cli.Context, rsp response) {

	verbose := c.GlobalBool("verbose")

	if verbose {
		fmt.Println(">", c.Command.Name, strings.Join(c.Args(), " "))
	}

	if !rsp.Code.IsOK() {
		fmt.Printf("-> code: %s\n", rsp.Code.String())
	}
	if rsp.Result != "" {
		fmt.Printf("%s", rsp.Result)
	}
	if len(rsp.Data) != 0 {
		//fmt.Printf("-> blockfreight data: %s\n", rsp.Data)
		fmt.Printf("-> data.hex: %X\n", rsp.Data)
	}
	if rsp.Log != "" {
		fmt.Printf("-> log: %s\n", rsp.Log)
	}
	if verbose {
		fmt.Println("")
	}

}

// =================================================
// Blockfreight™ | The blockchain of global freight.
// =================================================

// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBB                    BBBBBBBBBBBBBBBBBBB
// BBBBBBB                       BBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBB         BBBBBBBBBBBBBBBB
// BBBBBBB                     BBBBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBBB       BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBB       BBBBB
// BBBBBBB                       BBBB       BBBBB
// BBBBBBB                    BBBBBBB       BBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

// ==================================================
// Blockfreight™ | The blockchain for global freight.
// ==================================================
<commit_msg>Changing file to start creating blocks when bftnode is called<commit_after>// File: ./blockfreight/cmd/bftnode/bftnode.go
// Summary: Application code for Blockfreight™ | The blockchain of global freight.
// License: MIT License
// Company: Blockfreight, Inc.
// Author: Julian Nunez, Neil Tran, Julian Smith, Gian Felipe & contributors
// Site: https://blockfreight.com
// Support: <support@blockfreight.com>

// Copyright © 2017 Blockfreight, Inc. All Rights Reserved.

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// =================================================================================================================================================
// =================================================================================================================================================
//
// BBBBBBBBBBBb     lll                                kkk             ffff                         iii                  hhh            ttt
// BBBB``````BBBB   lll                                kkk            fff                           ```                  hhh            ttt
// BBBB      BBBB   lll      oooooo        ccccccc     kkk    kkkk  fffffff  rrr  rrr    eeeee      iii     gggggg ggg   hhh  hhhhh   tttttttt
// BBBBBBBBBBBB     lll    ooo    oooo    ccc    ccc   kkk   kkk    fffffff  rrrrrrrr eee    eeee   iii   gggg   ggggg   hhhh   hhhh  tttttttt
// BBBBBBBBBBBBBB   lll   ooo      ooo   ccc           kkkkkkk        fff    rrrr    eeeeeeeeeeeee  iii  gggg      ggg   hhh     hhh    ttt
// BBBB       BBB   lll   ooo      ooo   ccc           kkkk kkkk      fff    rrr     eeeeeeeeeeeee  iii   ggg      ggg   hhh     hhh    ttt
// BBBB      BBBB   lll   oooo    oooo   cccc    ccc   kkk   kkkk     fff    rrr      eee      eee  iii    ggg    gggg   hhh     hhh    tttt    ....
// BBBBBBBBBBBBB    lll     oooooooo       ccccccc     kkk     kkkk   fff    rrr       eeeeeeeee    iii     gggggg ggg   hhh     hhh     ttttt  ....
//                                                                                ggg      ggg
//   Blockfreight™ | The blockchain of global freight.                                                      ggggggggg
//
// =================================================================================================================================================
// =================================================================================================================================================

// Starts the Blockfreight™ Node to listen to all requests in the Blockfreight Network.
package main

import (
	// =======================
	// Golang Standard library
	// =======================
	"flag" // Implements command-line flag parsing.
	"fmt"  // Implements formatted I/O with functions analogous to C's printf and scanf.
	"log"  // Implements a simple logging package.

	// ===============
	// Tendermint Core
	// ===============
	"github.com/tendermint/abci/server"
	"github.com/tendermint/abci/types"
	tendermint "github.com/tendermint/go-common"

	// ======================
	// Blockfreight™ packages
	// ======================
	"github.com/blockfreight/blockfreight-alpha/lib/app/bft" // Implements the main functions to work with the Blockfreight™ Network.
)

func main() {

	fmt.Println("Blockfreight™ Node")
	// Parameters
	addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address")
	abciPtr := flag.String("bft", "socket", "socket | grpc")
	// persistencePtr := flag.String("persist", "", "directory to use for a database")
	flag.Parse()

	// Create the application - in memory or persisted to disk
	var app types.Application
	app = bft.NewBftApplication() //if *persistencePtr != "" => NewPersistentBftApplication(*persistencePtr)

	// Start the listener
	srv, err := server.NewServer(*addrPtr, *abciPtr, app)
	fmt.Println(srv)
	if err != nil {
		log.Fatal(err.Error())
	}
	fmt.Println("Service created by " + *abciPtr + " server")

	// Wait forever
	tendermint.TrapSignal(func() {
		// Cleanup
		fmt.Println("Stopping service")
		srv.Stop()
	})

}

// =================================================
// Blockfreight™ | The blockchain of global freight.
// =================================================

// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBB                    BBBBBBBBBBBBBBBBBBB
// BBBBBBB                       BBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBB         BBBBBBBBBBBBBBBB
// BBBBBBB                     BBBBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBBB       BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBB       BBBBB
// BBBBBBB                       BBBB       BBBBB
// BBBBBBB                    BBBBBBB       BBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

// ==================================================
// Blockfreight™ | The blockchain for global freight.
// ==================================================
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/golang/glog"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/api/v1"
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_4"
	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
)

const (
	kubeletAPIPodsURL = "http://127.0.0.1:10255/pods"
	ignorePath        = "/srv/kubernetes/manifests"
	activePath        = "/etc/kubernetes/manifests"
	manifestFilename  = "apiserver.json"
	kubeconfigPath    = "/etc/kubernetes/kubeconfig"
	secretsPath       = "/etc/kubernetes/checkpoint-secrets"
)

var (
	tempAPIServer      = []byte("temp-apiserver")
	kubeAPIServer      = []byte("kube-apiserver")
	activeManifest     = filepath.Join(activePath, manifestFilename)
	checkpointManifest = filepath.Join(ignorePath, manifestFilename)
	secureAPIAddr      = fmt.Sprintf("https://%s:%s", os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT_HTTPS"))
)

var tempAPIServerManifest = v1.Pod{
	TypeMeta: unversioned.TypeMeta{
		APIVersion: "v1",
		Kind:       "Pod",
	},
	ObjectMeta: v1.ObjectMeta{
		Name:      "temp-apiserver",
		Namespace: "kube-system",
	},
}

func main() {
	glog.Info("begin apiserver checkpointing...")
	run()
}

func run() {
	client := newAPIClient()
	for {
		var podList v1.PodList
		if err := json.Unmarshal(getPodsFromKubeletAPI(), &podList); err != nil {
			glog.Fatal(err)
		}
		switch {
		case bothAPIServersRunning(podList):
			glog.Info("both temp and kube apiserver running, removing temp apiserver")
			// Both the self-hosted API Server and the temp API Server are running.
			// Remove the temp API Server manifest from the config dir so that the
			// kubelet will stop it.
			if err := os.Remove(activeManifest); err != nil {
				glog.Error(err)
			}
		case kubeSystemAPIServerRunning(podList, client):
			glog.Info("kube-apiserver found, creating temp-apiserver manifest")
			// The self-hosted API Server is running. Let's snapshot the pod,
			// clean it up a bit, and then save it to the ignore path for
			// later use.
			tempAPIServerManifest.Spec = parseAPIPodSpec(podList)
			convertSecretsToVolumeMounts(client, &tempAPIServerManifest)
			writeManifest(tempAPIServerManifest)
			glog.Infof("finished creating temp-apiserver manifest at %s\n", checkpointManifest)

		default:
			glog.Info("no apiserver running, installing temp apiserver static manifest")
			b, err := ioutil.ReadFile(checkpointManifest)
			if err != nil {
				glog.Error(err)
			} else {
				if err := ioutil.WriteFile(activeManifest, b, 0644); err != nil {
					glog.Error(err)
				}
			}
		}
		time.Sleep(60 * time.Second)
	}
}

func getPodsFromKubeletAPI() []byte {
	var pods []byte
	res, err := http.Get(kubeletAPIPodsURL)
	if err != nil {
		glog.Error(err)
		return pods
	}
	pods, err = ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		glog.Error(err)
	}
	return pods
}

func bothAPIServersRunning(pods v1.PodList) bool {
	var kubeAPISeen, tempAPISeen bool
	for _, p := range pods.Items {
		kubeAPISeen = kubeAPISeen || isKubeAPI(p)
		tempAPISeen = tempAPISeen || isTempAPI(p)
		if kubeAPISeen && tempAPISeen {
			return true
		}
	}
	return false
}

func kubeSystemAPIServerRunning(pods v1.PodList, client clientset.Interface) bool {
	for _, p := range pods.Items {
		if isKubeAPI(p) {
			// Make sure it's actually running. Sometimes we get that
			// pod manifest back, but the server is not actually running.
			_, err := client.Discovery().ServerVersion()
			return err == nil
		}
	}
	return false
}

func isKubeAPI(pod v1.Pod) bool {
	return strings.Contains(pod.Name, "kube-apiserver") && pod.Namespace == api.NamespaceSystem
}

func isTempAPI(pod v1.Pod) bool {
	return strings.Contains(pod.Name, "temp-apiserver") && pod.Namespace == api.NamespaceSystem
}

// cleanVolumes will sanitize the list of volumes and volume mounts
// to remove the default service account token.
func cleanVolumes(p *v1.Pod) {
	volumes := make([]v1.Volume, 0, len(p.Spec.Volumes))
	for _, v := range p.Spec.Volumes {
		if !strings.HasPrefix(v.Name, "default-token") {
			volumes = append(volumes, v)
		}
	}
	p.Spec.Volumes = volumes
	for i := range p.Spec.Containers {
		c := &p.Spec.Containers[i]
		volumeMounts := make([]v1.VolumeMount, 0, len(c.VolumeMounts))
		for _, vm := range c.VolumeMounts {
			if !strings.HasPrefix(vm.Name, "default-token") {
				volumeMounts = append(volumeMounts, vm)
			}
		}
		c.VolumeMounts = volumeMounts
	}
}

// writeManifest will write the manifest to the ignore path.
// It first writes the file to a temp file, and then atomically moves it into
// the actual ignore path and correct file name.
func writeManifest(manifest v1.Pod) {
	m, err := json.Marshal(manifest)
	if err != nil {
		glog.Fatal(err)
	}
	writeAndAtomicCopy(m, checkpointManifest)
}

func parseAPIPodSpec(podList v1.PodList) v1.PodSpec {
	var apiPod v1.Pod
	for _, p := range podList.Items {
		if isKubeAPI(p) {
			apiPod = p
			break
		}
	}
	cleanVolumes(&apiPod)
	return apiPod.Spec
}

func newAPIClient() clientset.Interface {
	kubeConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfigPath},
		&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: secureAPIAddr}}).ClientConfig()
	if err != nil {
		glog.Fatal(err)
	}
	return clientset.NewForConfigOrDie(kubeConfig)
}

func convertSecretsToVolumeMounts(client clientset.Interface, pod *v1.Pod) {
	glog.Info("converting secrets to volume mounts")
	spec := pod.Spec
	for i := range spec.Volumes {
		v := &spec.Volumes[i]
		if v.Secret != nil {
			secretName := v.Secret.SecretName
			basePath := filepath.Join(secretsPath, pod.Name, v.Secret.SecretName)
			v.HostPath = &v1.HostPathVolumeSource{
				Path: basePath,
			}
			copySecretsToDisk(client, secretName, basePath)
			v.Secret = nil
			break
		}
	}
}

func copySecretsToDisk(client clientset.Interface, secretName, basePath string) {
	glog.Info("copying secrets to disk")
	if err := os.MkdirAll(basePath, 0755); err != nil {
		glog.Fatal(err)
	}
	glog.Infof("created directory %s", basePath)
	s, err := client.Core().Secrets(api.NamespaceSystem).Get(secretName)
	if err != nil {
		glog.Fatal(err)
	}
	for name, value := range s.Data {
		path := filepath.Join(basePath, name)
		writeAndAtomicCopy(value, path)
	}
}

func writeAndAtomicCopy(data []byte, path string) {
	// First write a "temp" file.
	tmpfile := filepath.Join(filepath.Dir(path), "."+filepath.Base(path))
	if err := ioutil.WriteFile(tmpfile, data, 0644); err != nil {
		glog.Fatal(err)
	}
	// Finally, copy that file to the correct location.
	if err := os.Rename(tmpfile, path); err != nil {
		glog.Fatal(err)
	}
}
<commit_msg>cmd/checkpoint: remove break statement from secret checkpoint loop (#147)<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/golang/glog"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/api/v1"
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_4"
	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
)

const (
	kubeletAPIPodsURL = "http://127.0.0.1:10255/pods"
	ignorePath        = "/srv/kubernetes/manifests"
	activePath        = "/etc/kubernetes/manifests"
	manifestFilename  = "apiserver.json"
	kubeconfigPath    = "/etc/kubernetes/kubeconfig"
	secretsPath       = "/etc/kubernetes/checkpoint-secrets"
)

var (
	tempAPIServer      = []byte("temp-apiserver")
	kubeAPIServer      = []byte("kube-apiserver")
	activeManifest     = filepath.Join(activePath, manifestFilename)
	checkpointManifest = filepath.Join(ignorePath, manifestFilename)
	secureAPIAddr      = fmt.Sprintf("https://%s:%s", os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT_HTTPS"))
)

var tempAPIServerManifest = v1.Pod{
	TypeMeta: unversioned.TypeMeta{
		APIVersion: "v1",
		Kind:       "Pod",
	},
	ObjectMeta: v1.ObjectMeta{
		Name:      "temp-apiserver",
		Namespace: "kube-system",
	},
}

func main() {
	glog.Info("begin apiserver checkpointing...")
	run()
}

func run() {
	client := newAPIClient()
	for {
		var podList v1.PodList
		if err := json.Unmarshal(getPodsFromKubeletAPI(), &podList); err != nil {
			glog.Fatal(err)
		}
		switch {
		case bothAPIServersRunning(podList):
			glog.Info("both temp and kube apiserver running, removing temp apiserver")
			// Both the self-hosted API Server and the temp API Server are running.
			// Remove the temp API Server manifest from the config dir so that the
			// kubelet will stop it.
			if err := os.Remove(activeManifest); err != nil {
				glog.Error(err)
			}
		case kubeSystemAPIServerRunning(podList, client):
			glog.Info("kube-apiserver found, creating temp-apiserver manifest")
			// The self-hosted API Server is running. Let's snapshot the pod,
			// clean it up a bit, and then save it to the ignore path for
			// later use.
			tempAPIServerManifest.Spec = parseAPIPodSpec(podList)
			convertSecretsToVolumeMounts(client, &tempAPIServerManifest)
			writeManifest(tempAPIServerManifest)
			glog.Infof("finished creating temp-apiserver manifest at %s\n", checkpointManifest)

		default:
			glog.Info("no apiserver running, installing temp apiserver static manifest")
			b, err := ioutil.ReadFile(checkpointManifest)
			if err != nil {
				glog.Error(err)
			} else {
				if err := ioutil.WriteFile(activeManifest, b, 0644); err != nil {
					glog.Error(err)
				}
			}
		}
		time.Sleep(60 * time.Second)
	}
}

func getPodsFromKubeletAPI() []byte {
	var pods []byte
	res, err := http.Get(kubeletAPIPodsURL)
	if err != nil {
		glog.Error(err)
		return pods
	}
	pods, err = ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		glog.Error(err)
	}
	return pods
}

func bothAPIServersRunning(pods v1.PodList) bool {
	var kubeAPISeen, tempAPISeen bool
	for _, p := range pods.Items {
		kubeAPISeen = kubeAPISeen || isKubeAPI(p)
		tempAPISeen = tempAPISeen || isTempAPI(p)
		if kubeAPISeen && tempAPISeen {
			return true
		}
	}
	return false
}

func kubeSystemAPIServerRunning(pods v1.PodList, client clientset.Interface) bool {
	for _, p := range pods.Items {
		if isKubeAPI(p) {
			// Make sure it's actually running. Sometimes we get that
			// pod manifest back, but the server is not actually running.
			_, err := client.Discovery().ServerVersion()
			return err == nil
		}
	}
	return false
}

func isKubeAPI(pod v1.Pod) bool {
	return strings.Contains(pod.Name, "kube-apiserver") && pod.Namespace == api.NamespaceSystem
}

func isTempAPI(pod v1.Pod) bool {
	return strings.Contains(pod.Name, "temp-apiserver") && pod.Namespace == api.NamespaceSystem
}

// cleanVolumes will sanitize the list of volumes and volume mounts
// to remove the default service account token.
func cleanVolumes(p *v1.Pod) {
	volumes := make([]v1.Volume, 0, len(p.Spec.Volumes))
	for _, v := range p.Spec.Volumes {
		if !strings.HasPrefix(v.Name, "default-token") {
			volumes = append(volumes, v)
		}
	}
	p.Spec.Volumes = volumes
	for i := range p.Spec.Containers {
		c := &p.Spec.Containers[i]
		volumeMounts := make([]v1.VolumeMount, 0, len(c.VolumeMounts))
		for _, vm := range c.VolumeMounts {
			if !strings.HasPrefix(vm.Name, "default-token") {
				volumeMounts = append(volumeMounts, vm)
			}
		}
		c.VolumeMounts = volumeMounts
	}
}

// writeManifest will write the manifest to the ignore path.
// It first writes the file to a temp file, and then atomically moves it into
// the actual ignore path and correct file name.
func writeManifest(manifest v1.Pod) {
	m, err := json.Marshal(manifest)
	if err != nil {
		glog.Fatal(err)
	}
	writeAndAtomicCopy(m, checkpointManifest)
}

func parseAPIPodSpec(podList v1.PodList) v1.PodSpec {
	var apiPod v1.Pod
	for _, p := range podList.Items {
		if isKubeAPI(p) {
			apiPod = p
			break
		}
	}
	cleanVolumes(&apiPod)
	return apiPod.Spec
}

func newAPIClient() clientset.Interface {
	kubeConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfigPath},
		&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: secureAPIAddr}}).ClientConfig()
	if err != nil {
		glog.Fatal(err)
	}
	return clientset.NewForConfigOrDie(kubeConfig)
}

func convertSecretsToVolumeMounts(client clientset.Interface, pod *v1.Pod) {
	glog.Info("converting secrets to volume mounts")
	spec := pod.Spec
	for i := range spec.Volumes {
		v := &spec.Volumes[i]
		if v.Secret != nil {
			secretName := v.Secret.SecretName
			basePath := filepath.Join(secretsPath, pod.Name, v.Secret.SecretName)
			v.HostPath = &v1.HostPathVolumeSource{
				Path: basePath,
			}
			copySecretsToDisk(client, secretName, basePath)
			v.Secret = nil
		}
	}
}

func copySecretsToDisk(client clientset.Interface, secretName, basePath string) {
	glog.Info("copying secrets to disk")
	if err := os.MkdirAll(basePath, 0755); err != nil {
		glog.Fatal(err)
	}
	glog.Infof("created directory %s", basePath)
	s, err := client.Core().Secrets(api.NamespaceSystem).Get(secretName)
	if err != nil {
		glog.Fatal(err)
	}
	for name, value := range s.Data {
		path := filepath.Join(basePath, name)
		writeAndAtomicCopy(value, path)
	}
}

func writeAndAtomicCopy(data []byte, path string) {
	// First write a "temp" file.
	tmpfile := filepath.Join(filepath.Dir(path), "."+filepath.Base(path))
	if err := ioutil.WriteFile(tmpfile, data, 0644); err != nil {
		glog.Fatal(err)
	}
	// Finally, copy that file to the correct location.
	if err := os.Rename(tmpfile, path); err != nil {
		glog.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. 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"
	"io/ioutil"
	"log"
	"net"
	"time"

	"github.com/google/key-transparency/core/client"
	"github.com/google/key-transparency/core/client/ctlog"
	"github.com/google/key-transparency/core/signatures"
	"github.com/google/key-transparency/core/vrf"
	"github.com/google/key-transparency/core/vrf/p256"
	"github.com/google/key-transparency/impl/google/authentication"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/oauth"

	pb "github.com/google/key-transparency/impl/proto/kt_service_v1"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "key-transparency-client",
	Short: "A client for interacting with the key transparency server",
	Long: `The key transparency client retrieves and sets keys in the
key transparency server.  The client verifies all cryptographic proofs the
server provides to ensure that account data is accurate.`,
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		log.Fatalf("%v", err)
	}
}

// Global flags for use by subcommands.
var (
	verbose bool
)

func init() {
	cobra.OnInitialize(initConfig)
	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", ".key-transparency.yaml", "config file (default is .key-transparency.yaml)")
	RootCmd.PersistentFlags().String("vrf", "testdata/vrf-pubkey.pem", "path to vrf public key")
	RootCmd.PersistentFlags().String("ct-url", "", "URL of Certificate Transparency server")
	RootCmd.PersistentFlags().String("ct-key", "testdata/ct-server-key-public.pem", "Path to public key PEM for Certificate Transparency server")
	RootCmd.PersistentFlags().String("kt-url", "", "URL of Key Transparency server")
	RootCmd.PersistentFlags().String("kt-key", "testdata/server.crt", "Path to public key for Key Transparency")

	RootCmd.PersistentFlags().String("kt-sig", "testdata/p256-pubkey.pem", "Path to public key for signed map heads")

	// Global flags for use by subcommands.
	RootCmd.PersistentFlags().DurationP("timeout", "t", 3*time.Second, "Time to wait before operations timeout")
	RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Print in/out and verification steps")
	viper.BindPFlags(RootCmd.PersistentFlags())
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	viper.AutomaticEnv() // Read in environment variables that match.

	if cfgFile == "" { // Skip if no config file is present.
		return
	}

	viper.SetConfigFile(cfgFile)
	if err := viper.ReadInConfig(); err != nil {
		log.Fatalf("Failed reading config file: %v: %v", viper.ConfigFileUsed(), err)
	}
}

func readVrfKey(vrfPubFile string) (vrf.PublicKey, error) {
	b, err := ioutil.ReadFile(vrfPubFile)
	if err != nil {
		return nil, fmt.Errorf("Error reading vrf public key: %v, %v", vrfPubFile, err)
	}
	v, err := p256.NewVRFVerifierFromPEM(b)
	if err != nil {
		return nil, fmt.Errorf("Error parsing vrf public key: %v", err)
	}
	return v, nil
}

// getTokenFromWeb uses config to request a Token.  Returns the retrieved Token.
func getTokenFromWeb(config *oauth2.Config) (*oauth2.Token, error) {
	// TODO: replace state token with something random to prevent CSRF.
	authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOnline)
	fmt.Printf("Go to the following link in your browser then type the "+
		"authorization code: \n%v\n", authURL)

	var code string
	if _, err := fmt.Scan(&code); err != nil {
		return nil, err
	}

	tok, err := config.Exchange(oauth2.NoContext, code)
	if err != nil {
		return nil, err
	}
	return tok, nil
}

func getCreds(clientSecretFile string) (credentials.PerRPCCredentials, error) {
	b, err := ioutil.ReadFile(clientSecretFile)
	if err != nil {
		return nil, err
	}

	config, err := google.ConfigFromJSON(b, authentication.RequiredScopes...)
	if err != nil {
		return nil, err
	}

	tok, err := getTokenFromWeb(config)
	if err != nil {
		return nil, err
	}
	return oauth.NewOauthAccess(tok), nil
}

func readSignatureVerifier(ktPEM string) (*signatures.Verifier, error) {
	pem, err := ioutil.ReadFile(ktPEM)
	if err != nil {
		return nil, err
	}
	pk, _, err := signatures.PublicKeyFromPEM(pem)
	if err != nil {
		return nil, err
	}
	ver, err := signatures.NewVerifier(pk)
	if err != nil {
		return nil, err
	}
	return ver, nil
}

func getClient(cc *grpc.ClientConn, vrfPubFile, ktSig, ctURL, ctPEM string) (*client.Client, error) {
	// Create CT client.
	pem, err := ioutil.ReadFile(ctPEM)
	if err != nil {
		return nil, fmt.Errorf("error reading ctPEM: %v", err)
	}
	ctClient, err := ctlog.New(pem, ctURL)
	if err != nil {
		return nil, fmt.Errorf("error creating CT client: %v", err)
	}

	// Create Key Transparency client.
	vrfKey, err := readVrfKey(vrfPubFile)
	if err != nil {
		return nil, err
	}
	verifier, err := readSignatureVerifier(ktSig)
	if err != nil {
		return nil, fmt.Errorf("error reading key transparency PEM: %v", err)
	}
	cli := pb.NewKeyTransparencyServiceClient(cc)
	return client.New(cli, vrfKey, verifier, ctClient), nil
}

func dial(ktURL, caFile, clientSecretFile string) (*grpc.ClientConn, error) {
	var opts []grpc.DialOption
	if true {
		host, _, err := net.SplitHostPort(ktURL)
		if err != nil {
			return nil, err
		}
		var creds credentials.TransportCredentials
		if caFile != "" {
			var err error
			creds, err = credentials.NewClientTLSFromFile(caFile, host)
			if err != nil {
				return nil, err
			}
		} else {
			// Use the local set of root certs.
			creds = credentials.NewClientTLSFromCert(nil, host)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	}

	if clientSecretFile != "" {
		creds, err := getCreds(clientSecretFile)
		if err != nil {
			return nil, err
		}
		opts = append(opts, grpc.WithPerRPCCredentials(creds))
	}
	cc, err := grpc.Dial(ktURL, opts...)
	if err != nil {
		return nil, err
	}
	return cc, nil
}

// GetClient connects to the server and returns a key transpency verification
// client.
func GetClient(clientSecretFile string) (*client.Client, error) {
	ktURL := viper.GetString("kt-url")
	ktPEM := viper.GetString("kt-key")
	ktSig := viper.GetString("kt-sig")
	ctURL := viper.GetString("ct-url")
	ctPEM := viper.GetString("ct-key")
	vrfFile := viper.GetString("vrf")
	cc, err := dial(ktURL, ktPEM, clientSecretFile)
	if err != nil {
		return nil, fmt.Errorf("Error Dialing %v: %v", ktURL, err)
	}
	c, err := getClient(cc, vrfFile, ktSig, ctURL, ctPEM)
	if err != nil {
		return nil, fmt.Errorf("Error creating client: %v", err)
	}
	return c, nil
}
<commit_msg>Home config path<commit_after>// Copyright 2016 Google Inc. 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"
	"io/ioutil"
	"log"
	"net"
	"time"

	"github.com/google/key-transparency/core/client"
	"github.com/google/key-transparency/core/client/ctlog"
	"github.com/google/key-transparency/core/signatures"
	"github.com/google/key-transparency/core/vrf"
	"github.com/google/key-transparency/core/vrf/p256"
	"github.com/google/key-transparency/impl/google/authentication"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/oauth"

	pb "github.com/google/key-transparency/impl/proto/kt_service_v1"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "key-transparency-client",
	Short: "A client for interacting with the key transparency server",
	Long: `The key transparency client retrieves and sets keys in the
key transparency server.  The client verifies all cryptographic proofs the
server provides to ensure that account data is accurate.`,
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		log.Fatalf("%v", err)
	}
}

// Global flags for use by subcommands.
var (
	verbose bool
)

func init() {
	cobra.OnInitialize(initConfig)
	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.key-transparency.yaml)")
	RootCmd.PersistentFlags().String("vrf", "testdata/vrf-pubkey.pem", "path to vrf public key")
	RootCmd.PersistentFlags().String("ct-url", "", "URL of Certificate Transparency server")
	RootCmd.PersistentFlags().String("ct-key", "testdata/ct-server-key-public.pem", "Path to public key PEM for Certificate Transparency server")
	RootCmd.PersistentFlags().String("kt-url", "", "URL of Key Transparency server")
	RootCmd.PersistentFlags().String("kt-key", "testdata/server.crt", "Path to public key for Key Transparency")

	RootCmd.PersistentFlags().String("kt-sig", "testdata/p256-pubkey.pem", "Path to public key for signed map heads")

	// Global flags for use by subcommands.
	RootCmd.PersistentFlags().DurationP("timeout", "t", 3*time.Second, "Time to wait before operations timeout")
	RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Print in/out and verification steps")
	viper.BindPFlags(RootCmd.PersistentFlags())
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	viper.AutomaticEnv() // Read in environment variables that match.

	if cfgFile != "" {
		viper.SetConfigFile(cfgFile)
		if err := viper.ReadInConfig(); err != nil {
			log.Fatalf("Failed reading config file: %v: %v", viper.ConfigFileUsed(), err)
		}
	} else {
		viper.SetConfigName(".key-transparency")
		viper.AddConfigPath("$HOME")
		if err := viper.ReadInConfig(); err == nil {
			fmt.Println("Using config file:", viper.ConfigFileUsed())
		}
	}
}

func readVrfKey(vrfPubFile string) (vrf.PublicKey, error) {
	b, err := ioutil.ReadFile(vrfPubFile)
	if err != nil {
		return nil, fmt.Errorf("Error reading vrf public key: %v, %v", vrfPubFile, err)
	}
	v, err := p256.NewVRFVerifierFromPEM(b)
	if err != nil {
		return nil, fmt.Errorf("Error parsing vrf public key: %v", err)
	}
	return v, nil
}

// getTokenFromWeb uses config to request a Token.  Returns the retrieved Token.
func getTokenFromWeb(config *oauth2.Config) (*oauth2.Token, error) {
	// TODO: replace state token with something random to prevent CSRF.
	authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOnline)
	fmt.Printf("Go to the following link in your browser then type the "+
		"authorization code: \n%v\n", authURL)

	var code string
	if _, err := fmt.Scan(&code); err != nil {
		return nil, err
	}

	tok, err := config.Exchange(oauth2.NoContext, code)
	if err != nil {
		return nil, err
	}
	return tok, nil
}

func getCreds(clientSecretFile string) (credentials.PerRPCCredentials, error) {
	b, err := ioutil.ReadFile(clientSecretFile)
	if err != nil {
		return nil, err
	}

	config, err := google.ConfigFromJSON(b, authentication.RequiredScopes...)
	if err != nil {
		return nil, err
	}

	tok, err := getTokenFromWeb(config)
	if err != nil {
		return nil, err
	}
	return oauth.NewOauthAccess(tok), nil
}

func readSignatureVerifier(ktPEM string) (*signatures.Verifier, error) {
	pem, err := ioutil.ReadFile(ktPEM)
	if err != nil {
		return nil, err
	}
	pk, _, err := signatures.PublicKeyFromPEM(pem)
	if err != nil {
		return nil, err
	}
	ver, err := signatures.NewVerifier(pk)
	if err != nil {
		return nil, err
	}
	return ver, nil
}

func getClient(cc *grpc.ClientConn, vrfPubFile, ktSig, ctURL, ctPEM string) (*client.Client, error) {
	// Create CT client.
	pem, err := ioutil.ReadFile(ctPEM)
	if err != nil {
		return nil, fmt.Errorf("error reading ctPEM: %v", err)
	}
	ctClient, err := ctlog.New(pem, ctURL)
	if err != nil {
		return nil, fmt.Errorf("error creating CT client: %v", err)
	}

	// Create Key Transparency client.
	vrfKey, err := readVrfKey(vrfPubFile)
	if err != nil {
		return nil, err
	}
	verifier, err := readSignatureVerifier(ktSig)
	if err != nil {
		return nil, fmt.Errorf("error reading key transparency PEM: %v", err)
	}
	cli := pb.NewKeyTransparencyServiceClient(cc)
	return client.New(cli, vrfKey, verifier, ctClient), nil
}

func dial(ktURL, caFile, clientSecretFile string) (*grpc.ClientConn, error) {
	var opts []grpc.DialOption
	if true {
		host, _, err := net.SplitHostPort(ktURL)
		if err != nil {
			return nil, err
		}
		var creds credentials.TransportCredentials
		if caFile != "" {
			var err error
			creds, err = credentials.NewClientTLSFromFile(caFile, host)
			if err != nil {
				return nil, err
			}
		} else {
			// Use the local set of root certs.
			creds = credentials.NewClientTLSFromCert(nil, host)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	}

	if clientSecretFile != "" {
		creds, err := getCreds(clientSecretFile)
		if err != nil {
			return nil, err
		}
		opts = append(opts, grpc.WithPerRPCCredentials(creds))
	}
	cc, err := grpc.Dial(ktURL, opts...)
	if err != nil {
		return nil, err
	}
	return cc, nil
}

// GetClient connects to the server and returns a key transpency verification
// client.
func GetClient(clientSecretFile string) (*client.Client, error) {
	ktURL := viper.GetString("kt-url")
	ktPEM := viper.GetString("kt-key")
	ktSig := viper.GetString("kt-sig")
	ctURL := viper.GetString("ct-url")
	ctPEM := viper.GetString("ct-key")
	vrfFile := viper.GetString("vrf")
	cc, err := dial(ktURL, ktPEM, clientSecretFile)
	if err != nil {
		return nil, fmt.Errorf("Error Dialing %v: %v", ktURL, err)
	}
	c, err := getClient(cc, vrfFile, ktSig, ctURL, ctPEM)
	if err != nil {
		return nil, fmt.Errorf("Error creating client: %v", err)
	}
	return c, nil
}
<|endoftext|>


<commit_before>package command

import (
	_ "github.com/go-sql-driver/mysql"
)
<commit_msg>still struggle with golang gotcha<commit_after>package command

import (
//_ "github.com/go-sql-driver/mysql"
)
<|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 main

import (
	"errors"
	"os"
	"regexp"
	"text/template"

	"github.com/codegangsta/cli"
	"github.com/kubernetes/helm/pkg/format"
)

var (
	errMissingDeploymentArg = errors.New("First argument, deployment name, is required. Try 'helm get --help'")
	errTooManyArgs          = errors.New("Too many arguments provided. Try 'helm dep describe [DEPLOYMENT]'")
)

const deploymentDesc = `A deployment is an instance of a Chart running in the cluster.

   Deployments have a name, a chart, and possibly a set of properites. The deployment
   commands provide tools for managing deployments.

   To deploy a new chart, use the top-level 'helm deploy' command. From there,
   the 'helm deployment' commands may be used to work with the deployed
   application.

   For more help, use 'helm deployment CMD -h'.`

const defaultShowFormat = `Name: {{.Name}}
Status: {{.State.Status}}
{{with .State.Errors}}Errors:
{{range .}}  {{.}}{{end}}
{{end}}`

func init() {
	addCommands(deploymentCommands())
}

func deploymentCommands() cli.Command {
	return cli.Command{
		// Names following form prescribed here: http://is.gd/QUSEOF
		Name:        "deployment",
		Aliases:     []string{"dep"},
		Usage:       "Perform deployment-centered operations.",
		Description: deploymentDesc,
		Subcommands: []cli.Command{
			{
				Name:      "config",
				Usage:     "Dump the configuration file for this deployment.",
				ArgsUsage: "DEPLOYMENT",
			},
			{
				Name:      "remove",
				Aliases:   []string{"rm"},
				Usage:     "Deletes the named deployment(s).",
				ArgsUsage: "DEPLOYMENT [DEPLOYMENT [...]]",
				Action:    func(c *cli.Context) { run(c, deleteDeployment) },
			},
			{
				Name:      "describe",
				Usage:     "Describes the kubernetes resources for the named deployment(s).",
				ArgsUsage: "DEPLOYMENT",
				Action:    func(c *cli.Context) { run(c, describeDeployment) },
			},
			{
				Name:      "manifest",
				Usage:     "Dump the Kubernetes manifest file for this deployment.",
				ArgsUsage: "DEPLOYMENT",
			},
			{
				Name:      "show",
				Aliases:   []string{"info"},
				Usage:     "Provide details about this deployment.",
				ArgsUsage: "",
				Action:    func(c *cli.Context) { run(c, showDeployment) },
			},
			{
				Name:      "list",
				Aliases:   []string{"ls"},
				Usage:     "list all deployments, or filter by an optional regular expression.",
				ArgsUsage: "REGEXP",
				Action:    func(c *cli.Context) { run(c, listDeployments) },
			},
		},
	}
}

func listDeployments(c *cli.Context) error {
	list, err := NewClient(c).ListDeployments()
	if err != nil {
		return err
	}
	args := c.Args()
	if len(args) >= 1 {
		pattern := args[0]
		r, err := regexp.Compile(pattern)
		if err != nil {
			return err
		}

		newlist := []string{}
		for _, i := range list {
			if r.MatchString(i) {
				newlist = append(newlist, i)
			}
		}
		list = newlist
	}

	if len(list) == 0 {
		return errors.New("no deployments found")
	}

	format.List(list)
	return nil
}

func deleteDeployment(c *cli.Context) error {
	args := c.Args()
	if len(args) < 1 {
		return errMissingDeploymentArg
	}
	for _, name := range args {
		deployment, err := NewClient(c).DeleteDeployment(name)
		if err != nil {
			return err
		}
		format.Info("Deleted %q at %s", name, deployment.DeletedAt)
	}
	return nil
}

func describeDeployment(c *cli.Context) error {
	args := c.Args()
	if len(args) < 1 {
		return errMissingDeploymentArg
	}
	if len(args) > 1 {
		return errTooManyArgs
	}
	name := args[0]
	_, err := NewClient(c).DescribeDeployment(name)
	if err != nil {
		return err
	}

	format.Info("TO BE IMPLEMENTED")

	return nil
}

func showDeployment(c *cli.Context) error {
	args := c.Args()
	if len(args) < 1 {
		return errMissingDeploymentArg
	}
	name := args[0]
	deployment, err := NewClient(c).GetDeployment(name)
	if err != nil {
		return err
	}
	tmpl := template.Must(template.New("show").Parse(defaultShowFormat))
	return tmpl.Execute(os.Stdout, deployment)
}
<commit_msg>fix(cli): remove unused 'helm dep' subcommands<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 main

import (
	"errors"
	"os"
	"regexp"
	"text/template"

	"github.com/codegangsta/cli"
	"github.com/kubernetes/helm/pkg/format"
)

var (
	errMissingDeploymentArg = errors.New("First argument, deployment name, is required. Try 'helm get --help'")
	errTooManyArgs          = errors.New("Too many arguments provided. Try 'helm dep describe [DEPLOYMENT]'")
)

const deploymentDesc = `A deployment is an instance of a Chart running in the cluster.

   Deployments have a name, a chart, and possibly a set of properites. The deployment
   commands provide tools for managing deployments.

   To deploy a new chart, use the top-level 'helm deploy' command. From there,
   the 'helm deployment' commands may be used to work with the deployed
   application.

   For more help, use 'helm deployment CMD -h'.`

const defaultShowFormat = `Name: {{.Name}}
Status: {{.State.Status}}
{{with .State.Errors}}Errors:
{{range .}}  {{.}}{{end}}
{{end}}`

func init() {
	addCommands(deploymentCommands())
}

func deploymentCommands() cli.Command {
	return cli.Command{
		// Names following form prescribed here: http://is.gd/QUSEOF
		Name:        "deployment",
		Aliases:     []string{"dep"},
		Usage:       "Perform deployment-centered operations.",
		Description: deploymentDesc,
		Subcommands: []cli.Command{
			{
				Name:      "remove",
				Aliases:   []string{"rm"},
				Usage:     "Deletes the named deployment(s).",
				ArgsUsage: "DEPLOYMENT [DEPLOYMENT [...]]",
				Action:    func(c *cli.Context) { run(c, deleteDeployment) },
			},
			{
				Name:      "describe",
				Usage:     "Describes the kubernetes resources for the named deployment(s).",
				ArgsUsage: "DEPLOYMENT",
				Action:    func(c *cli.Context) { run(c, describeDeployment) },
			},
			{
				Name:      "show",
				Aliases:   []string{"info"},
				Usage:     "Provide details about this deployment.",
				ArgsUsage: "",
				Action:    func(c *cli.Context) { run(c, showDeployment) },
			},
			{
				Name:      "list",
				Aliases:   []string{"ls"},
				Usage:     "list all deployments, or filter by an optional regular expression.",
				ArgsUsage: "REGEXP",
				Action:    func(c *cli.Context) { run(c, listDeployments) },
			},
		},
	}
}

func listDeployments(c *cli.Context) error {
	list, err := NewClient(c).ListDeployments()
	if err != nil {
		return err
	}
	args := c.Args()
	if len(args) >= 1 {
		pattern := args[0]
		r, err := regexp.Compile(pattern)
		if err != nil {
			return err
		}

		newlist := []string{}
		for _, i := range list {
			if r.MatchString(i) {
				newlist = append(newlist, i)
			}
		}
		list = newlist
	}

	if len(list) == 0 {
		return errors.New("no deployments found")
	}

	format.List(list)
	return nil
}

func deleteDeployment(c *cli.Context) error {
	args := c.Args()
	if len(args) < 1 {
		return errMissingDeploymentArg
	}
	for _, name := range args {
		deployment, err := NewClient(c).DeleteDeployment(name)
		if err != nil {
			return err
		}
		format.Info("Deleted %q at %s", name, deployment.DeletedAt)
	}
	return nil
}

func describeDeployment(c *cli.Context) error {
	args := c.Args()
	if len(args) < 1 {
		return errMissingDeploymentArg
	}
	if len(args) > 1 {
		return errTooManyArgs
	}
	name := args[0]
	_, err := NewClient(c).DescribeDeployment(name)
	if err != nil {
		return err
	}

	format.Info("TO BE IMPLEMENTED")

	return nil
}

func showDeployment(c *cli.Context) error {
	args := c.Args()
	if len(args) < 1 {
		return errMissingDeploymentArg
	}
	name := args[0]
	deployment, err := NewClient(c).GetDeployment(name)
	if err != nil {
		return err
	}
	tmpl := template.Must(template.New("show").Parse(defaultShowFormat))
	return tmpl.Execute(os.Stdout, deployment)
}
<|endoftext|>


<commit_before>// Copyright 2015 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"net"
	"os"
	"os/signal"
	"sort"
	"syscall"
	"time"

	"github.com/mikioh/ipaddr"
	"github.com/mikioh/ipoam"
	"golang.org/x/net/icmp"
)

var rtUsageTmpl = `Usage:
	ipoam {{.Name}} [flags] destination

destination
	A hostname, DNS reg-name or IP address.

`

var (
	cmdRT = &Command{
		Func:      rtMain,
		Usage:     cmdUsage,
		UsageTmpl: rtUsageTmpl,
		CanonName: "rt",
		Aliases:   []string{"pathdisc", "traceroute"},
		Descr:     "Discover an IP-layer path",
	}

	rtPayload []byte
	rtData    = []byte("0123456789abcdefghijklmnopqrstuvwxyz")

	rtIPv4only    bool
	rtIPv6only    bool
	rtNoRevLookup bool
	rtUseICMP     bool
	rtVerbose     bool

	rtMaxHops          int
	rtTC               int
	rtPayloadLen       int
	rtPerHopProbeCount int
	rtPort             int
	rtWait             int

	rtOutboundIf string
	rtSrc        string
)

func init() {
	cmdRT.Flag.BoolVar(&rtIPv4only, "4", false, "Run IPv4 test only")
	cmdRT.Flag.BoolVar(&rtIPv6only, "6", false, "Run IPv6 test only")
	cmdRT.Flag.BoolVar(&rtNoRevLookup, "n", false, "Don't use DNS reverse lookup")
	cmdRT.Flag.BoolVar(&rtUseICMP, "m", false, "Use ICMP for probe packets instead of UDP")
	cmdRT.Flag.BoolVar(&rtVerbose, "v", false, "Show verbose information")

	cmdRT.Flag.IntVar(&rtMaxHops, "hops", 30, "Maximum IPv4 TTL or IPv6 hop-limit")
	cmdRT.Flag.IntVar(&rtTC, "tc", 0, "IPv4 TOS or IPv6 traffic-class on probe packets")
	cmdRT.Flag.IntVar(&rtPayloadLen, "pldlen", 56, "Probe packet payload length")
	cmdRT.Flag.IntVar(&rtPerHopProbeCount, "count", 3, "Per-hop probe count")
	cmdRT.Flag.IntVar(&rtPort, "port", 33434, "Base destination port, range will be [port, port+hops)")
	cmdRT.Flag.IntVar(&rtWait, "wait", 1, "Seconds between transmitting each probe")

	cmdRT.Flag.StringVar(&rtOutboundIf, "if", "", "Outbound interface name")
	cmdRT.Flag.StringVar(&rtSrc, "src", "", "Source IP address")
}

func rtMain(cmd *Command, args []string) {
	if len(args) == 0 {
		cmd.Flag.Usage()
	}

	bw := bufio.NewWriter(os.Stdout)

	c, ifi, err := parseDsts(args[0], rtIPv4only, rtIPv6only)
	if err != nil {
		cmd.fatal(err)
	}

	if rtMaxHops > 255 {
		rtMaxHops = 255
	}
	rtPayload = bytes.Repeat(rtData, int(rtPayloadLen)/len(rtData)+1)
	rtPayload = rtPayload[:rtPayloadLen]
	if rtWait <= 0 {
		rtWait = 1
	}
	if rtOutboundIf != "" {
		oif, err := net.InterfaceByName(rtOutboundIf)
		if err == nil {
			ifi = oif
		}
	}
	var src net.IP
	if rtSrc != "" {
		src = net.ParseIP(rtSrc)
		if src.To4() != nil {
			rtIPv4only = true
		}
		if src.To16() != nil && src.To4() == nil {
			rtIPv6only = true
		}
	}

	var ipt *ipoam.Tester
	var dst *ipaddr.Position
	for pos := c.First(); pos != nil; pos = c.Next() {
		if !rtIPv6only && pos.IP.To4() != nil {
			network := "udp4"
			address := "0.0.0.0:0"
			if src != nil {
				address = net.JoinHostPort(src.String(), "0")
			}
			if rtUseICMP {
				network = "ip4:icmp"
				address = "0.0.0.0"
				if src != nil {
					address = src.String()
				}
			}
			ipt, err = ipoam.NewTester(network, address)
			if err != nil {
				cmd.fatal(err)
			}
			defer ipt.Close()
			if rtTC >= 0 {
				ipt.IPv4PacketConn().SetTOS(rtTC)
			}
			dst = pos
			break
		}
		if !rtIPv4only && pos.IP.To16() != nil && pos.IP.To4() == nil {
			network := "udp6"
			address := "[::]:0"
			if src != nil {
				address = net.JoinHostPort(src.String(), "0")
			}
			if rtUseICMP {
				network = "ip6:ipv6-icmp"
				address = "::"
				if src != nil {
					address = src.String()
				}
			}
			ipt, err = ipoam.NewTester(network, address)
			if err != nil {
				cmd.fatal(err)
			}
			defer ipt.Close()
			if rtTC >= 0 {
				ipt.IPv6PacketConn().SetTrafficClass(rtTC)
			}
			dst = pos
			break
		}
	}
	c.Reset(nil)
	if dst == nil {
		cmd.fatal(fmt.Errorf("destination for %s not found", args[0]))
	}

	printRTBanner(bw, args[0], c, dst)

	sig := make(chan os.Signal)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
	cm := ipoam.ControlMessage{ID: os.Getpid() & 0xffff, Seq: 1, Port: rtPort}
	hops := make([]rtHop, 0)
	for i := 1; i <= rtMaxHops; i++ {
		var r ipoam.Report
		hops = hops[:0]

		for j := 0; j < rtPerHopProbeCount; j++ {
			t := time.NewTimer(time.Duration(rtWait) * time.Second)
			defer t.Stop()
			begin := time.Now()
			if !rtIPv6only && dst.IP.To4() != nil {
				ipt.IPv4PacketConn().SetTTL(i)
			}
			if !rtIPv4only && dst.IP.To16() != nil && dst.IP.To4() == nil {
				ipt.IPv6PacketConn().SetHopLimit(i)
			}
			if err := ipt.Probe(rtPayload, &cm, dst.IP, ifi); err != nil {
				fmt.Fprintf(os.Stdout, "error=%q\n", err)
			}

			cm.Seq++
			if cm.Seq > 0xffff {
				cm.Seq = 1
			}
			cm.Port++
			if cm.Port > 0xffff {
				cm.Port = rtPort
			}

			select {
			case <-sig:
				os.Exit(0)
			case <-t.C:
				hops = append(hops, rtHop{rtt: time.Since(begin), r: ipoam.Report{Src: net.IPv6unspecified}})
			case r = <-ipt.Report():
				hops = append(hops, rtHop{rtt: r.Time.Sub(begin), r: r})
			}
		}

		printRTReport(bw, i, hops)
		if hasReached(&r) {
			break
		}
	}
	os.Exit(0)
}

func printRTBanner(bw *bufio.Writer, dsts string, c *ipaddr.Cursor, pos *ipaddr.Position) {
	fmt.Fprintf(bw, "Path discovery for %s: %d hops max, %d per-hop probes, %d bytes payload\n", dsts, rtMaxHops, rtPerHopProbeCount, len(rtPayload))
	if len(c.List()) > 1 {
		fmt.Fprintf(bw, "Warning: %s has multiple addresses, using %v\n", dsts, pos.IP)
	}
	bw.Flush()
}

func printRTReport(bw *bufio.Writer, i int, hops []rtHop) {
	sort.Sort(rtHops(hops))
	fmt.Fprintf(bw, "% 3d  ", i)
	var prev net.IP
	for _, h := range hops {
		if h.r.Error != nil {
			continue
		}
		if h.r.Src.Equal(prev) {
			fmt.Fprintf(bw, "  %v", h.rtt)
			continue
		}
		if prev != nil {
			fmt.Fprintf(bw, "\n     ")
		}
		if h.r.Src.IsUnspecified() {
			fmt.Fprintf(bw, "*")
		} else {
			fmt.Fprintf(bw, "%s", literalOrName(h.r.Src.String(), rtNoRevLookup))
			if rtVerbose {
				if h.r.Dst != nil {
					fmt.Fprintf(bw, " tc=%#x hops=%d to=%v", h.r.TC, h.r.Hops, h.r.Dst)
				}
				if h.r.Interface != nil {
					fmt.Fprintf(bw, " if=%s", h.r.Interface.Name)
				}
				switch body := h.r.ICMP.Body.(type) {
				case *icmp.DstUnreach:
					printICMPExtensions(bw, body.Extensions)
				case *icmp.ParamProb:
					printICMPExtensions(bw, body.Extensions)
				case *icmp.TimeExceeded:
					printICMPExtensions(bw, body.Extensions)
				}
			}
		}
		fmt.Fprintf(bw, "  %v", h.rtt)
		prev = h.r.Src
	}
	fmt.Fprintf(bw, "\n")
	bw.Flush()
}

type rtHop struct {
	rtt time.Duration
	r   ipoam.Report
}

type rtHops []rtHop

func (hops rtHops) Len() int { return len(hops) }

func (hops rtHops) Less(i, j int) bool {
	if n := bytes.Compare(hops[i].r.Src, hops[j].r.Src); n < 0 {
		return true
	}
	return false
}

func (hops rtHops) Swap(i, j int) { hops[i], hops[j] = hops[j], hops[i] }

func printICMPExtensions(w io.Writer, exts []icmp.Extension) {
	for _, ext := range exts {
		switch ext := ext.(type) {
		case *icmp.MPLSLabelStack:
			for _, l := range ext.Labels {
				fmt.Fprintf(w, " <label=%d tc=%#x s=%t ttl=%d>", l.Label, l.TC, l.S, l.TTL)
			}
		case *icmp.InterfaceInfo:
			fmt.Fprintf(w, " <")
			if ext.Interface != nil {
				fmt.Fprintf(w, "if=%s", ext.Interface.Name)
			}
			if ext.Addr != nil {
				if ext.Interface != nil {
					fmt.Fprintf(w, " ")
				}
				fmt.Fprintf(w, "addr=%v", ext.Addr)
			}
			fmt.Fprintf(w, ">")
		}
	}
}
<commit_msg>ipoam/cmd/ipoam: more robust dstunreach handling<commit_after>// Copyright 2015 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"net"
	"os"
	"os/signal"
	"sort"
	"syscall"
	"time"

	"github.com/mikioh/ipaddr"
	"github.com/mikioh/ipoam"
	"golang.org/x/net/icmp"
)

var rtUsageTmpl = `Usage:
	ipoam {{.Name}} [flags] destination

destination
	A hostname, DNS reg-name or IP address.

`

var (
	cmdRT = &Command{
		Func:      rtMain,
		Usage:     cmdUsage,
		UsageTmpl: rtUsageTmpl,
		CanonName: "rt",
		Aliases:   []string{"pathdisc", "traceroute"},
		Descr:     "Discover an IP-layer path",
	}

	rtPayload []byte
	rtData    = []byte("0123456789abcdefghijklmnopqrstuvwxyz")

	rtIPv4only    bool
	rtIPv6only    bool
	rtNoRevLookup bool
	rtUseICMP     bool
	rtVerbose     bool

	rtMaxHops          int
	rtTC               int
	rtPayloadLen       int
	rtPerHopProbeCount int
	rtPort             int
	rtWait             int

	rtOutboundIf string
	rtSrc        string
)

func init() {
	cmdRT.Flag.BoolVar(&rtIPv4only, "4", false, "Run IPv4 test only")
	cmdRT.Flag.BoolVar(&rtIPv6only, "6", false, "Run IPv6 test only")
	cmdRT.Flag.BoolVar(&rtNoRevLookup, "n", false, "Don't use DNS reverse lookup")
	cmdRT.Flag.BoolVar(&rtUseICMP, "m", false, "Use ICMP for probe packets instead of UDP")
	cmdRT.Flag.BoolVar(&rtVerbose, "v", false, "Show verbose information")

	cmdRT.Flag.IntVar(&rtMaxHops, "hops", 30, "Maximum IPv4 TTL or IPv6 hop-limit")
	cmdRT.Flag.IntVar(&rtTC, "tc", 0, "IPv4 TOS or IPv6 traffic-class on probe packets")
	cmdRT.Flag.IntVar(&rtPayloadLen, "pldlen", 56, "Probe packet payload length")
	cmdRT.Flag.IntVar(&rtPerHopProbeCount, "count", 3, "Per-hop probe count")
	cmdRT.Flag.IntVar(&rtPort, "port", 33434, "Base destination port, range will be [port, port+hops)")
	cmdRT.Flag.IntVar(&rtWait, "wait", 1, "Seconds between transmitting each probe")

	cmdRT.Flag.StringVar(&rtOutboundIf, "if", "", "Outbound interface name")
	cmdRT.Flag.StringVar(&rtSrc, "src", "", "Source IP address")
}

func rtMain(cmd *Command, args []string) {
	if len(args) == 0 {
		cmd.Flag.Usage()
	}

	bw := bufio.NewWriter(os.Stdout)

	c, ifi, err := parseDsts(args[0], rtIPv4only, rtIPv6only)
	if err != nil {
		cmd.fatal(err)
	}

	if rtMaxHops > 255 {
		rtMaxHops = 255
	}
	rtPayload = bytes.Repeat(rtData, int(rtPayloadLen)/len(rtData)+1)
	rtPayload = rtPayload[:rtPayloadLen]
	if rtWait <= 0 {
		rtWait = 1
	}
	if rtOutboundIf != "" {
		oif, err := net.InterfaceByName(rtOutboundIf)
		if err == nil {
			ifi = oif
		}
	}
	var src net.IP
	if rtSrc != "" {
		src = net.ParseIP(rtSrc)
		if src.To4() != nil {
			rtIPv4only = true
		}
		if src.To16() != nil && src.To4() == nil {
			rtIPv6only = true
		}
	}

	var ipt *ipoam.Tester
	var dst *ipaddr.Position
	for pos := c.First(); pos != nil; pos = c.Next() {
		if !rtIPv6only && pos.IP.To4() != nil {
			network := "udp4"
			address := "0.0.0.0:0"
			if src != nil {
				address = net.JoinHostPort(src.String(), "0")
			}
			if rtUseICMP {
				network = "ip4:icmp"
				address = "0.0.0.0"
				if src != nil {
					address = src.String()
				}
			}
			ipt, err = ipoam.NewTester(network, address)
			if err != nil {
				cmd.fatal(err)
			}
			defer ipt.Close()
			if rtTC >= 0 {
				ipt.IPv4PacketConn().SetTOS(rtTC)
			}
			dst = pos
			break
		}
		if !rtIPv4only && pos.IP.To16() != nil && pos.IP.To4() == nil {
			network := "udp6"
			address := "[::]:0"
			if src != nil {
				address = net.JoinHostPort(src.String(), "0")
			}
			if rtUseICMP {
				network = "ip6:ipv6-icmp"
				address = "::"
				if src != nil {
					address = src.String()
				}
			}
			ipt, err = ipoam.NewTester(network, address)
			if err != nil {
				cmd.fatal(err)
			}
			defer ipt.Close()
			if rtTC >= 0 {
				ipt.IPv6PacketConn().SetTrafficClass(rtTC)
			}
			dst = pos
			break
		}
	}
	c.Reset(nil)
	if dst == nil {
		cmd.fatal(fmt.Errorf("destination for %s not found", args[0]))
	}

	printRTBanner(bw, args[0], c, dst)

	sig := make(chan os.Signal)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
	cm := ipoam.ControlMessage{ID: os.Getpid() & 0xffff, Seq: 1, Port: rtPort}
	hops := make([]rtHop, 0)
	for i := 1; i <= rtMaxHops; i++ {
		var reached bool
		var r ipoam.Report
		hops = hops[:0]

		for j := 0; j < rtPerHopProbeCount; j++ {
			t := time.NewTimer(time.Duration(rtWait) * time.Second)
			defer t.Stop()
			begin := time.Now()
			if !rtIPv6only && dst.IP.To4() != nil {
				ipt.IPv4PacketConn().SetTTL(i)
			}
			if !rtIPv4only && dst.IP.To16() != nil && dst.IP.To4() == nil {
				ipt.IPv6PacketConn().SetHopLimit(i)
			}
			if err := ipt.Probe(rtPayload, &cm, dst.IP, ifi); err != nil {
				fmt.Fprintf(os.Stdout, "error=%q\n", err)
			}

			cm.Seq++
			if cm.Seq > 0xffff {
				cm.Seq = 1
			}
			cm.Port++
			if cm.Port > 0xffff {
				cm.Port = rtPort
			}

			select {
			case <-sig:
				os.Exit(0)
			case <-t.C:
				hops = append(hops, rtHop{rtt: time.Since(begin), r: ipoam.Report{Src: net.IPv6unspecified}})
			case r = <-ipt.Report():
				hops = append(hops, rtHop{rtt: r.Time.Sub(begin), r: r})
			}
			if !reached {
				reached = hasReached(&r)
			}
		}

		printRTReport(bw, i, hops)
		if reached {
			break
		}
	}
	os.Exit(0)
}

func printRTBanner(bw *bufio.Writer, dsts string, c *ipaddr.Cursor, pos *ipaddr.Position) {
	fmt.Fprintf(bw, "Path discovery for %s: %d hops max, %d per-hop probes, %d bytes payload\n", dsts, rtMaxHops, rtPerHopProbeCount, len(rtPayload))
	if len(c.List()) > 1 {
		fmt.Fprintf(bw, "Warning: %s has multiple addresses, using %v\n", dsts, pos.IP)
	}
	bw.Flush()
}

func printRTReport(bw *bufio.Writer, i int, hops []rtHop) {
	sort.Sort(rtHops(hops))
	fmt.Fprintf(bw, "% 3d  ", i)
	var prev net.IP
	for _, h := range hops {
		if h.r.Error != nil {
			continue
		}
		if h.r.Src.Equal(prev) {
			fmt.Fprintf(bw, "  %v", h.rtt)
			continue
		}
		if prev != nil {
			fmt.Fprintf(bw, "\n     ")
		}
		if h.r.Src.IsUnspecified() {
			fmt.Fprintf(bw, "*")
		} else {
			fmt.Fprintf(bw, "%s", literalOrName(h.r.Src.String(), rtNoRevLookup))
			if rtVerbose {
				if h.r.Dst != nil {
					fmt.Fprintf(bw, " tc=%#x hops=%d to=%v", h.r.TC, h.r.Hops, h.r.Dst)
				}
				if h.r.Interface != nil {
					fmt.Fprintf(bw, " if=%s", h.r.Interface.Name)
				}
				switch body := h.r.ICMP.Body.(type) {
				case *icmp.DstUnreach:
					printICMPExtensions(bw, body.Extensions)
				case *icmp.ParamProb:
					printICMPExtensions(bw, body.Extensions)
				case *icmp.TimeExceeded:
					printICMPExtensions(bw, body.Extensions)
				}
			}
		}
		fmt.Fprintf(bw, "  %v", h.rtt)
		prev = h.r.Src
	}
	fmt.Fprintf(bw, "\n")
	bw.Flush()
}

type rtHop struct {
	rtt time.Duration
	r   ipoam.Report
}

type rtHops []rtHop

func (hops rtHops) Len() int { return len(hops) }

func (hops rtHops) Less(i, j int) bool {
	if n := bytes.Compare(hops[i].r.Src, hops[j].r.Src); n < 0 {
		return true
	}
	return false
}

func (hops rtHops) Swap(i, j int) { hops[i], hops[j] = hops[j], hops[i] }

func printICMPExtensions(w io.Writer, exts []icmp.Extension) {
	for _, ext := range exts {
		switch ext := ext.(type) {
		case *icmp.MPLSLabelStack:
			for _, l := range ext.Labels {
				fmt.Fprintf(w, " <label=%d tc=%#x s=%t ttl=%d>", l.Label, l.TC, l.S, l.TTL)
			}
		case *icmp.InterfaceInfo:
			fmt.Fprintf(w, " <")
			if ext.Interface != nil {
				fmt.Fprintf(w, "if=%s", ext.Interface.Name)
			}
			if ext.Addr != nil {
				if ext.Interface != nil {
					fmt.Fprintf(w, " ")
				}
				fmt.Fprintf(w, "addr=%v", ext.Addr)
			}
			fmt.Fprintf(w, ">")
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"github.com/pierrre/mangadownloader"
	"net/url"
	"os"
)

func main() {
	flag.Parse()

	out, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	md := mangadownloader.CreateDefaultMangeDownloader()

	for _, arg := range flag.Args() {
		u, err := url.Parse(arg)
		if err != nil {
			panic(err)
		}
		o, err := md.Identify(u)
		if err != nil {
			panic(err)
		}
		switch object := o.(type) {
		case *mangadownloader.Manga:
			err := md.DownloadManga(object, out)
			if err != nil {
				panic(err)
			}
		default:
			panic(errors.New("Not supported"))
		}
	}
}
<commit_msg>Add command flag "out" (output directory)<commit_after>package main

import (
	"errors"
	"flag"
	"github.com/pierrre/mangadownloader"
	"net/url"
	"os"
	"path/filepath"
)

func main() {
	outFlag := flag.String("out", "", "Output directory")
	flag.Parse()

	out := *outFlag
	if !filepath.IsAbs(out) {
		currentDir, err := os.Getwd()
		if err != nil {
			panic(err)
		}
		out = filepath.Join(currentDir, out)
	}

	md := mangadownloader.CreateDefaultMangeDownloader()

	for _, arg := range flag.Args() {
		u, err := url.Parse(arg)
		if err != nil {
			panic(err)
		}
		o, err := md.Identify(u)
		if err != nil {
			panic(err)
		}
		switch object := o.(type) {
		case *mangadownloader.Manga:
			err := md.DownloadManga(object, out)
			if err != nil {
				panic(err)
			}
		default:
			panic(errors.New("Not supported"))
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"

	"github.com/cloudflare/cfssl/api"
	"github.com/cloudflare/cfssl/auth"
	"github.com/cloudflare/cfssl/helpers"
	"github.com/cloudflare/cfssl/log"
	"github.com/cloudflare/cfssl/signer"
	metrics "github.com/cloudflare/go-metrics"
)

// A SignatureResponse contains only a certificate, as there is no other
// useful data for the CA to return at this time.
type SignatureResponse struct {
	Certificate string `json:"certificate"`
}

type filter func(string, *signer.SignRequest) bool

var filters = map[string][]filter{}

var stats struct {
	Registry         metrics.Registry
	Requests         map[string]metrics.Counter
	RequestRate      map[string]metrics.Meter
	TotalRequestRate metrics.Meter
	ErrorPercent     metrics.GaugeFloat64
	ErrorRate        metrics.Meter
}

func initStats() {
	stats.Registry = metrics.NewRegistry()

	stats.Requests = map[string]metrics.Counter{}
	stats.RequestRate = map[string]metrics.Meter{}

	// signers is defined in ca.go
	for k := range signers {
		stats.Requests[k] = metrics.NewRegisteredCounter("requests:"+k, stats.Registry)
		stats.RequestRate[k] = metrics.NewRegisteredMeter("request-rate:"+k, stats.Registry)
	}

	stats.TotalRequestRate = metrics.NewRegisteredMeter("total-request-rate", stats.Registry)
	stats.ErrorPercent = metrics.NewRegisteredGaugeFloat64("error-percent", stats.Registry)
	stats.ErrorRate = metrics.NewRegisteredMeter("error-rate", stats.Registry)
}

// incError increments the error count and updates the error percentage.
func incErrors() {
	stats.ErrorRate.Mark(1)
	eCtr := float64(stats.ErrorRate.Count())
	rCtr := float64(stats.TotalRequestRate.Count())
	stats.ErrorPercent.Update(eCtr / rCtr * 100)
}

// incRequests increments the request count and updates the error percentage.
func incRequests() {
	stats.TotalRequestRate.Mark(1)
	eCtr := float64(stats.ErrorRate.Count())
	rCtr := float64(stats.TotalRequestRate.Count())
	stats.ErrorPercent.Update(eCtr / rCtr * 100)
}

func fail(w http.ResponseWriter, req *http.Request, status, code int, msg, ad string) {
	incErrors()

	if ad != "" {
		ad = " (" + ad + ")"
	}
	log.Errorf("[HTTP %d] %d - %s%s", status, code, msg, ad)

	dumpReq, err := httputil.DumpRequest(req, true)
	if err != nil {
		fmt.Printf("%v#v\n", req)
	} else {
		fmt.Printf("%s\n", dumpReq)
	}

	res := api.NewErrorResponse(msg, code)
	w.WriteHeader(status)
	jenc := json.NewEncoder(w)
	jenc.Encode(res)
}

func dispatchRequest(w http.ResponseWriter, req *http.Request) {
	incRequests()

	if req.Method != "POST" {
		fail(w, req, http.StatusMethodNotAllowed, 1, "only POST is permitted", "")
		return
	}

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		fail(w, req, http.StatusInternalServerError, 1, err.Error(), "while reading request body")
		return
	}
	defer req.Body.Close()

	var authReq auth.AuthenticatedRequest
	err = json.Unmarshal(body, &authReq)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, err.Error(), "while unmarshaling request body")
		return
	}

	var sigRequest signer.SignRequest
	err = json.Unmarshal(authReq.Request, &sigRequest)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, err.Error(), "while unmarshalling authenticated request")
		return
	}

	if sigRequest.Label == "" {
		sigRequest.Label = defaultLabel
	}

	stats.Requests[sigRequest.Label].Inc(1)
	stats.RequestRate[sigRequest.Label].Mark(1)

	s, ok := signers[sigRequest.Label]
	if !ok {
		fail(w, req, http.StatusBadRequest, 1, "bad request", "request is for non-existent label "+sigRequest.Label)
		return
	}

	// Sanity checks to ensure that we have a valid policy. This
	// should have been checked in NewAuthSignHandler.
	policy := s.Policy()
	if policy == nil {
		fail(w, req, http.StatusInternalServerError, 1, "invalid policy", "signer was initialised without a signing policy")
		return
	}
	profile := policy.Default

	if policy.Profiles != nil && sigRequest.Profile != "" {
		profile = policy.Profiles[sigRequest.Profile]
	}

	if profile == nil {
		fail(w, req, http.StatusInternalServerError, 1, "invalid profile", "signer was initialised without any valid profiles")
		return
	}

	if profile.Provider == nil {
		fail(w, req, http.StatusUnauthorized, 1, "authorisation required", "received unauthenticated request")
		return
	}

	if !profile.Provider.Verify(&authReq) {
		fail(w, req, http.StatusBadRequest, 1, "invalid token", "received authenticated request with invalid token")
		return
	}

	if sigRequest.Request == "" {
		fail(w, req, http.StatusBadRequest, 1, "invalid request", "empty request")
		return
	}

	signReq := signer.SignRequest{
		Hostname: sigRequest.Hostname,
		Request:  sigRequest.Request,
		Subject:  sigRequest.Subject,
		Profile:  sigRequest.Profile,
		Label:    sigRequest.Label,
	}

	cert, err := s.Sign(signReq)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, "bad request", "signature failed: "+err.Error())
		return
	}

	x509Cert, err := helpers.ParseCertificatePEM(cert)
	if err != nil {
		fail(w, req, http.StatusInternalServerError, 1, "bad certificate", err.Error())
	}

	log.Infof("signature: requester=%s, label=%s, profile=%s, serialno=%s",
		req.RemoteAddr, sigRequest.Label, sigRequest.Profile, x509Cert.SerialNumber)

	res := api.NewSuccessResponse(&SignatureResponse{Certificate: string(cert)})
	jenc := json.NewEncoder(w)
	err = jenc.Encode(res)
	if err != nil {
		log.Errorf("error writing response: %v", err)
	}
}

func dumpMetrics(w http.ResponseWriter, req *http.Request) {
	out, err := json.Marshal(stats.Registry)
	if err != nil {
		log.Errorf("failed to dump metrics: %v", err)
	}

	w.Write(out)
}
<commit_msg>Update multiroot CA with recent changes to structs.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"

	"github.com/cloudflare/cfssl/api"
	"github.com/cloudflare/cfssl/auth"
	"github.com/cloudflare/cfssl/helpers"
	"github.com/cloudflare/cfssl/log"
	"github.com/cloudflare/cfssl/signer"
	metrics "github.com/cloudflare/go-metrics"
)

// A SignatureResponse contains only a certificate, as there is no other
// useful data for the CA to return at this time.
type SignatureResponse struct {
	Certificate string `json:"certificate"`
}

type filter func(string, *signer.SignRequest) bool

var filters = map[string][]filter{}

var stats struct {
	Registry         metrics.Registry
	Requests         map[string]metrics.Counter
	RequestRate      map[string]metrics.Meter
	TotalRequestRate metrics.Meter
	ErrorPercent     metrics.GaugeFloat64
	ErrorRate        metrics.Meter
}

func initStats() {
	stats.Registry = metrics.NewRegistry()

	stats.Requests = map[string]metrics.Counter{}
	stats.RequestRate = map[string]metrics.Meter{}

	// signers is defined in ca.go
	for k := range signers {
		stats.Requests[k] = metrics.NewRegisteredCounter("requests:"+k, stats.Registry)
		stats.RequestRate[k] = metrics.NewRegisteredMeter("request-rate:"+k, stats.Registry)
	}

	stats.TotalRequestRate = metrics.NewRegisteredMeter("total-request-rate", stats.Registry)
	stats.ErrorPercent = metrics.NewRegisteredGaugeFloat64("error-percent", stats.Registry)
	stats.ErrorRate = metrics.NewRegisteredMeter("error-rate", stats.Registry)
}

// incError increments the error count and updates the error percentage.
func incErrors() {
	stats.ErrorRate.Mark(1)
	eCtr := float64(stats.ErrorRate.Count())
	rCtr := float64(stats.TotalRequestRate.Count())
	stats.ErrorPercent.Update(eCtr / rCtr * 100)
}

// incRequests increments the request count and updates the error percentage.
func incRequests() {
	stats.TotalRequestRate.Mark(1)
	eCtr := float64(stats.ErrorRate.Count())
	rCtr := float64(stats.TotalRequestRate.Count())
	stats.ErrorPercent.Update(eCtr / rCtr * 100)
}

func fail(w http.ResponseWriter, req *http.Request, status, code int, msg, ad string) {
	incErrors()

	if ad != "" {
		ad = " (" + ad + ")"
	}
	log.Errorf("[HTTP %d] %d - %s%s", status, code, msg, ad)

	dumpReq, err := httputil.DumpRequest(req, true)
	if err != nil {
		fmt.Printf("%v#v\n", req)
	} else {
		fmt.Printf("%s\n", dumpReq)
	}

	res := api.NewErrorResponse(msg, code)
	w.WriteHeader(status)
	jenc := json.NewEncoder(w)
	jenc.Encode(res)
}

func dispatchRequest(w http.ResponseWriter, req *http.Request) {
	incRequests()

	if req.Method != "POST" {
		fail(w, req, http.StatusMethodNotAllowed, 1, "only POST is permitted", "")
		return
	}

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		fail(w, req, http.StatusInternalServerError, 1, err.Error(), "while reading request body")
		return
	}
	defer req.Body.Close()

	var authReq auth.AuthenticatedRequest
	err = json.Unmarshal(body, &authReq)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, err.Error(), "while unmarshaling request body")
		return
	}

	var sigRequest signer.SignRequest
	err = json.Unmarshal(authReq.Request, &sigRequest)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, err.Error(), "while unmarshalling authenticated request")
		return
	}

	if sigRequest.Label == "" {
		sigRequest.Label = defaultLabel
	}

	stats.Requests[sigRequest.Label].Inc(1)
	stats.RequestRate[sigRequest.Label].Mark(1)

	s, ok := signers[sigRequest.Label]
	if !ok {
		fail(w, req, http.StatusBadRequest, 1, "bad request", "request is for non-existent label "+sigRequest.Label)
		return
	}

	// Sanity checks to ensure that we have a valid policy. This
	// should have been checked in NewAuthSignHandler.
	policy := s.Policy()
	if policy == nil {
		fail(w, req, http.StatusInternalServerError, 1, "invalid policy", "signer was initialised without a signing policy")
		return
	}
	profile := policy.Default

	if policy.Profiles != nil && sigRequest.Profile != "" {
		profile = policy.Profiles[sigRequest.Profile]
	}

	if profile == nil {
		fail(w, req, http.StatusInternalServerError, 1, "invalid profile", "signer was initialised without any valid profiles")
		return
	}

	if profile.Provider == nil {
		fail(w, req, http.StatusUnauthorized, 1, "authorisation required", "received unauthenticated request")
		return
	}

	if !profile.Provider.Verify(&authReq) {
		fail(w, req, http.StatusBadRequest, 1, "invalid token", "received authenticated request with invalid token")
		return
	}

	if sigRequest.Request == "" {
		fail(w, req, http.StatusBadRequest, 1, "invalid request", "empty request")
		return
	}

	cert, err := s.Sign(sigRequest)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, "bad request", "signature failed: "+err.Error())
		return
	}

	x509Cert, err := helpers.ParseCertificatePEM(cert)
	if err != nil {
		fail(w, req, http.StatusInternalServerError, 1, "bad certificate", err.Error())
	}

	log.Infof("signature: requester=%s, label=%s, profile=%s, serialno=%s",
		req.RemoteAddr, sigRequest.Label, sigRequest.Profile, x509Cert.SerialNumber)

	res := api.NewSuccessResponse(&SignatureResponse{Certificate: string(cert)})
	jenc := json.NewEncoder(w)
	err = jenc.Encode(res)
	if err != nil {
		log.Errorf("error writing response: %v", err)
	}
}

func dumpMetrics(w http.ResponseWriter, req *http.Request) {
	out, err := json.Marshal(stats.Registry)
	if err != nil {
		log.Errorf("failed to dump metrics: %v", err)
	}

	w.Write(out)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"flag"
	"net"
	"os"
	"strconv"
	"time"

	"github.com/coredns/coredns/coremain"
	_ "github.com/coredns/coredns/plugin/bind"
	_ "github.com/coredns/coredns/plugin/cache"
	_ "github.com/coredns/coredns/plugin/errors"
	_ "github.com/coredns/coredns/plugin/forward"
	_ "github.com/coredns/coredns/plugin/health"
	_ "github.com/coredns/coredns/plugin/log"
	_ "github.com/coredns/coredns/plugin/loop"
	_ "github.com/coredns/coredns/plugin/metrics"
	clog "github.com/coredns/coredns/plugin/pkg/log"
	_ "github.com/coredns/coredns/plugin/reload"
	"github.com/mholt/caddy"
	"k8s.io/dns/pkg/netif"
	"k8s.io/kubernetes/pkg/util/dbus"
	utilexec "k8s.io/kubernetes/pkg/util/exec"
	utiliptables "k8s.io/kubernetes/pkg/util/iptables"
)

// configParams lists the configuration options that can be provided to dns-cache
type configParams struct {
	localIP   string        // ip address for the local cache agent to listen for dns requests
	localPort string        // port to listen for dns requests
	intfName  string        // Name of the interface to be created
	interval  time.Duration // specifies how often to run iptables rules check
	exitChan  chan bool     // Channel to terminate background goroutines
}

type iptablesRule struct {
	table utiliptables.Table
	chain utiliptables.Chain
	args  []string
}

type cacheApp struct {
	iptables      utiliptables.Interface
	iptablesRules []iptablesRule
	params        configParams
	netifHandle   *netif.NetifManager
}

var cache = cacheApp{params: configParams{localPort: "53"}}

func (c *cacheApp) Init() {
	err := c.parseAndValidateFlags()
	if err != nil {
		clog.Fatalf("Error parsing flags - %s, Exiting", err)
	}
	c.netifHandle = netif.NewNetifManager(net.ParseIP(c.params.localIP))
	c.initIptables()
	err = c.teardownNetworking()
	if err != nil {
		// It is likely to hit errors here if previous shutdown cleaned up all iptables rules and interface.
		// Logging error at info level
		clog.Infof("Hit error during teardown - %s", err)
	}
	err = c.setupNetworking()
	if err != nil {
		cache.teardownNetworking()
		clog.Fatalf("Failed to setup - %s, Exiting", err)
	}
}

func init() {
	cache.Init()
	caddy.OnProcessExit = append(caddy.OnProcessExit, func() { cache.teardownNetworking() })
}

func (c *cacheApp) initIptables() {

	c.iptablesRules = []iptablesRule{
		// Match traffic destined for localIp:localPort and set the flows to be NOTRACKED, this skips connection tracking
		{utiliptables.Table("raw"), utiliptables.ChainPrerouting, []string{"-p", "tcp", "-d", c.params.localIP,
			"--dport", c.params.localPort, "-j", "NOTRACK"}},
		{utiliptables.Table("raw"), utiliptables.ChainPrerouting, []string{"-p", "udp", "-d", c.params.localIP,
			"--dport", c.params.localPort, "-j", "NOTRACK"}},
		// There are rules in filter table to allow tracked connections to be accepted. Since we skipped connection tracking,
		// need these additional filter table rules.
		{utiliptables.TableFilter, utiliptables.ChainInput, []string{"-p", "tcp", "-d", c.params.localIP,
			"--dport", c.params.localPort, "-j", "ACCEPT"}},
		{utiliptables.TableFilter, utiliptables.ChainInput, []string{"-p", "udp", "-d", c.params.localIP,
			"--dport", c.params.localPort, "-j", "ACCEPT"}},
		// Match traffic from localIp:localPort and set the flows to be NOTRACKED, this skips connection tracking
		{utiliptables.Table("raw"), utiliptables.ChainOutput, []string{"-p", "tcp", "-s", c.params.localIP,
			"--sport", c.params.localPort, "-j", "NOTRACK"}},
		{utiliptables.Table("raw"), utiliptables.ChainOutput, []string{"-p", "udp", "-s", c.params.localIP,
			"--sport", c.params.localPort, "-j", "NOTRACK"}},
		// Additional filter table rules for traffic frpm localIp:localPort
		{utiliptables.TableFilter, utiliptables.ChainOutput, []string{"-p", "tcp", "-s", c.params.localIP,
			"--sport", c.params.localPort, "-j", "ACCEPT"}},
		{utiliptables.TableFilter, utiliptables.ChainOutput, []string{"-p", "udp", "-s", c.params.localIP,
			"--sport", c.params.localPort, "-j", "ACCEPT"}},
	}
	c.iptables = newIPTables()
}

func newIPTables() utiliptables.Interface {
	execer := utilexec.New()
	dbus := dbus.New()
	return utiliptables.New(execer, dbus, utiliptables.ProtocolIpv4)
}

func (c *cacheApp) setupNetworking() error {
	var err error
	clog.Infof("Setting up networking for node cache")
	err = c.netifHandle.AddDummyDevice(c.params.intfName)
	if err != nil {
		return err
	}
	for _, rule := range c.iptablesRules {
		_, err = c.iptables.EnsureRule(utiliptables.Prepend, rule.table, rule.chain, rule.args...)
		if err != nil {
			return err
		}
	}
	return err
}

func (c *cacheApp) teardownNetworking() error {
	clog.Infof("Tearing down")
	if c.params.exitChan != nil {
		// Stop the goroutine that periodically checks for iptables rules/dummy interface
		// exitChan is a buffered channel of size 1, so this will not block
		c.params.exitChan <- true
	}
	err := c.netifHandle.RemoveDummyDevice(c.params.intfName)
	for _, rule := range c.iptablesRules {
		exists := true
		for exists == true {
			c.iptables.DeleteRule(rule.table, rule.chain, rule.args...)
			exists, _ = c.iptables.EnsureRule(utiliptables.Prepend, rule.table, rule.chain, rule.args...)
		}
		// Delete the rule one last time since EnsureRule creates the rule if it doesn't exist
		c.iptables.DeleteRule(rule.table, rule.chain, rule.args...)
	}
	return err
}

func (c *cacheApp) parseAndValidateFlags() error {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Runs coreDNS v1.2.5 as a nodelocal cache listening on the specified ip:port")
		flag.PrintDefaults()
	}

	flag.StringVar(&c.params.localIP, "localip", "", "ip address to bind dnscache to")
	flag.StringVar(&c.params.intfName, "intfname", "nodelocaldns", "name of the interface to be created")
	flag.DurationVar(&c.params.interval, "syncinterval", 60, "interval(in seconds) to check for iptables rules")
	flag.Parse()

	if net.ParseIP(c.params.localIP) == nil {
		return fmt.Errorf("Invalid localip specified - %q", c.params.localIP)
	}
	// lookup specified dns port
	if f := flag.Lookup("dns.port"); f == nil {
		return fmt.Errorf("Failed to lookup \"dns.port\" parameter")
	} else {
		c.params.localPort = f.Value.String()
	}
	if _, err := strconv.Atoi(c.params.localPort); err != nil {
		return fmt.Errorf("Invalid port specified - %q", c.params.localPort)
	}
	return nil
}

func (c *cacheApp) runChecks() {
	for _, rule := range c.iptablesRules {
		exists, err := c.iptables.EnsureRule(utiliptables.Prepend, rule.table, rule.chain, rule.args...)
		if !exists {
			if err != nil {
				cache.teardownNetworking()
				clog.Fatalf("Failed to add back non-existent rule %v", rule)
			}
			clog.Infof("Added back nonexistent rule - %v", rule)
		}
		if err != nil {
			clog.Errorf("Failed to check rule %v - %s", rule, err)
		}
	}

	exists, err := c.netifHandle.EnsureDummyDevice(c.params.intfName)
	if !exists {
		if err != nil {
			cache.teardownNetworking()
			clog.Fatalf("Failed to add back non-existent interface %s", c.params.intfName)
		}
		clog.Infof("Added back nonexistent interface - %s", c.params.intfName)
	}
	if err != nil {
		clog.Errorf("Failed to check dummy device %s - %s", c.params.intfName, err)
	}
}

func (c *cacheApp) run() {
	c.params.exitChan = make(chan bool, 1)
	tick := time.NewTicker(c.params.interval * time.Second)
	for {
		select {
		case <-tick.C:
			c.runChecks()
		case <-c.params.exitChan:
			clog.Warningf("Exiting iptables check goroutine")
			return
		}
	}
}

func main() {
	// Ensure that the required setup is ready
	// https://github.com/kubernetes/dns/issues/282 sometimes the interface gets the ip and then loses it, if added too soon.
	cache.runChecks()
	go cache.run()
	coremain.Run()
	// Unlikely to reach here, if we did it is because coremain exited and the signal was not trapped.
	clog.Errorf("Untrapped signal, tearing down")
	cache.teardownNetworking()
}
<commit_msg>Handle iptables lock error when running checks<commit_after>package main

import (
	"fmt"

	"flag"
	"net"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/coredns/coredns/coremain"
	_ "github.com/coredns/coredns/plugin/bind"
	_ "github.com/coredns/coredns/plugin/cache"
	_ "github.com/coredns/coredns/plugin/errors"
	_ "github.com/coredns/coredns/plugin/forward"
	_ "github.com/coredns/coredns/plugin/health"
	_ "github.com/coredns/coredns/plugin/log"
	_ "github.com/coredns/coredns/plugin/loop"
	_ "github.com/coredns/coredns/plugin/metrics"
	clog "github.com/coredns/coredns/plugin/pkg/log"
	_ "github.com/coredns/coredns/plugin/reload"
	"github.com/mholt/caddy"
	"k8s.io/dns/pkg/netif"
	"k8s.io/kubernetes/pkg/util/dbus"
	utilexec "k8s.io/kubernetes/pkg/util/exec"
	utiliptables "k8s.io/kubernetes/pkg/util/iptables"
)

// configParams lists the configuration options that can be provided to dns-cache
type configParams struct {
	localIP            string        // ip address for the local cache agent to listen for dns requests
	localPort          string        // port to listen for dns requests
	intfName           string        // Name of the interface to be created
	interval           time.Duration // specifies how often to run iptables rules check
	maxIptablesLockErr int           // Max consecutive iptables lock errors to ignore before restarting
	exitChan           chan bool     // Channel to terminate background goroutines
}

type iptablesRule struct {
	table utiliptables.Table
	chain utiliptables.Chain
	args  []string
}

type cacheApp struct {
	iptables      utiliptables.Interface
	iptablesRules []iptablesRule
	params        configParams
	netifHandle   *netif.NetifManager
}

var cache = cacheApp{params: configParams{localPort: "53"}}

func IsIPTablesLocked(err error) bool {
	return strings.Contains(err.Error(), "holding the xtables lock")
}

func (c *cacheApp) Init() {
	err := c.parseAndValidateFlags()
	if err != nil {
		clog.Fatalf("Error parsing flags - %s, Exiting", err)
	}
	c.netifHandle = netif.NewNetifManager(net.ParseIP(c.params.localIP))
	c.initIptables()
	err = c.teardownNetworking()
	if err != nil {
		// It is likely to hit errors here if previous shutdown cleaned up all iptables rules and interface.
		// Logging error at info level
		clog.Infof("Hit error during teardown - %s", err)
	}
	err = c.setupNetworking()
	if err != nil {
		cache.teardownNetworking()
		clog.Fatalf("Failed to setup - %s, Exiting", err)
	}
}

func init() {
	cache.Init()
	caddy.OnProcessExit = append(caddy.OnProcessExit, func() { cache.teardownNetworking() })
}

func (c *cacheApp) initIptables() {

	c.iptablesRules = []iptablesRule{
		// Match traffic destined for localIp:localPort and set the flows to be NOTRACKED, this skips connection tracking
		{utiliptables.Table("raw"), utiliptables.ChainPrerouting, []string{"-p", "tcp", "-d", c.params.localIP,
			"--dport", c.params.localPort, "-j", "NOTRACK"}},
		{utiliptables.Table("raw"), utiliptables.ChainPrerouting, []string{"-p", "udp", "-d", c.params.localIP,
			"--dport", c.params.localPort, "-j", "NOTRACK"}},
		// There are rules in filter table to allow tracked connections to be accepted. Since we skipped connection tracking,
		// need these additional filter table rules.
		{utiliptables.TableFilter, utiliptables.ChainInput, []string{"-p", "tcp", "-d", c.params.localIP,
			"--dport", c.params.localPort, "-j", "ACCEPT"}},
		{utiliptables.TableFilter, utiliptables.ChainInput, []string{"-p", "udp", "-d", c.params.localIP,
			"--dport", c.params.localPort, "-j", "ACCEPT"}},
		// Match traffic from localIp:localPort and set the flows to be NOTRACKED, this skips connection tracking
		{utiliptables.Table("raw"), utiliptables.ChainOutput, []string{"-p", "tcp", "-s", c.params.localIP,
			"--sport", c.params.localPort, "-j", "NOTRACK"}},
		{utiliptables.Table("raw"), utiliptables.ChainOutput, []string{"-p", "udp", "-s", c.params.localIP,
			"--sport", c.params.localPort, "-j", "NOTRACK"}},
		// Additional filter table rules for traffic frpm localIp:localPort
		{utiliptables.TableFilter, utiliptables.ChainOutput, []string{"-p", "tcp", "-s", c.params.localIP,
			"--sport", c.params.localPort, "-j", "ACCEPT"}},
		{utiliptables.TableFilter, utiliptables.ChainOutput, []string{"-p", "udp", "-s", c.params.localIP,
			"--sport", c.params.localPort, "-j", "ACCEPT"}},
	}
	c.iptables = newIPTables()
}

func newIPTables() utiliptables.Interface {
	execer := utilexec.New()
	dbus := dbus.New()
	return utiliptables.New(execer, dbus, utiliptables.ProtocolIpv4)
}

func (c *cacheApp) setupNetworking() error {
	var err error
	clog.Infof("Setting up networking for node cache")
	err = c.netifHandle.AddDummyDevice(c.params.intfName)
	if err != nil {
		return err
	}
	for _, rule := range c.iptablesRules {
		_, err = c.iptables.EnsureRule(utiliptables.Prepend, rule.table, rule.chain, rule.args...)
		if err != nil {
			return err
		}
	}
	return err
}

func (c *cacheApp) teardownNetworking() error {
	clog.Infof("Tearing down")
	if c.params.exitChan != nil {
		// Stop the goroutine that periodically checks for iptables rules/dummy interface
		// exitChan is a buffered channel of size 1, so this will not block
		c.params.exitChan <- true
	}
	err := c.netifHandle.RemoveDummyDevice(c.params.intfName)
	for _, rule := range c.iptablesRules {
		exists := true
		for exists == true {
			c.iptables.DeleteRule(rule.table, rule.chain, rule.args...)
			exists, _ = c.iptables.EnsureRule(utiliptables.Prepend, rule.table, rule.chain, rule.args...)
		}
		// Delete the rule one last time since EnsureRule creates the rule if it doesn't exist
		c.iptables.DeleteRule(rule.table, rule.chain, rule.args...)
	}
	return err
}

func (c *cacheApp) parseAndValidateFlags() error {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Runs coreDNS v1.2.5 as a nodelocal cache listening on the specified ip:port")
		flag.PrintDefaults()
	}

	flag.StringVar(&c.params.localIP, "localip", "", "ip address to bind dnscache to")
	flag.StringVar(&c.params.intfName, "intfname", "nodelocaldns", "name of the interface to be created")
	flag.DurationVar(&c.params.interval, "syncinterval", 60, "interval(in seconds) to check for iptables rules")
	flag.IntVar(&c.params.maxIptablesLockErr, "maxiptableslockerr", 10, "Max consecutive iptables lock errors to ignore before restarting")
	flag.Parse()

	if net.ParseIP(c.params.localIP) == nil {
		return fmt.Errorf("Invalid localip specified - %q", c.params.localIP)
	}
	// lookup specified dns port
	if f := flag.Lookup("dns.port"); f == nil {
		return fmt.Errorf("Failed to lookup \"dns.port\" parameter")
	} else {
		c.params.localPort = f.Value.String()
	}
	if _, err := strconv.Atoi(c.params.localPort); err != nil {
		return fmt.Errorf("Invalid port specified - %q", c.params.localPort)
	}
	if c.params.maxIptablesLockErr < 0 {
		return fmt.Errorf("Invalid value for maxIptablesLockErr - %d", c.params.maxIptablesLockErr)
	}
	return nil
}

// returns true if checks failed due to iptables lock issue
func (c *cacheApp) runChecks() bool {
	iptablesLocked := false
	for _, rule := range c.iptablesRules {
		exists, err := c.iptables.EnsureRule(utiliptables.Prepend, rule.table, rule.chain, rule.args...)
		if exists {
			continue
		} else if err == nil {
			clog.Infof("Added back nonexistent rule - %v", rule)
			continue
		}
		// if we got here, either iptables check failed or adding rule back failed.
		if IsIPTablesLocked(err) {
			clog.Infof("Failed to check/add back rule %v, due to xtables lock in use, retrying in %v seconds", rule, c.params.interval)
			iptablesLocked = true
		} else {
			cache.teardownNetworking()
			clog.Fatalf("Failed to add back non-existent rule %v - %s", rule, err)
		}
	}

	exists, err := c.netifHandle.EnsureDummyDevice(c.params.intfName)
	if !exists {
		if err != nil {
			cache.teardownNetworking()
			clog.Fatalf("Failed to add back non-existent interface %s", c.params.intfName)
		}
		clog.Infof("Added back nonexistent interface - %s", c.params.intfName)
	}
	if err != nil {
		clog.Errorf("Failed to check dummy device %s - %s", c.params.intfName, err)
	}
	return iptablesLocked
}

func (c *cacheApp) run() {
	c.params.exitChan = make(chan bool, 1)
	tick := time.NewTicker(c.params.interval * time.Second)
	numLockErr := 0
	iptablesLocked := false
	for {
		select {
		case <-tick.C:
			iptablesLocked = c.runChecks()
			if iptablesLocked {
				numLockErr++
			} else {
				numLockErr = 0
			}
			if numLockErr > c.params.maxIptablesLockErr {
				cache.teardownNetworking()
				clog.Fatalf("Too many consecutive failures when running iptables checks")
			}
		case <-c.params.exitChan:
			clog.Warningf("Exiting iptables check goroutine")
			return
		}
	}
}

func main() {
	// Ensure that the required setup is ready
	// https://github.com/kubernetes/dns/issues/282 sometimes the interface gets the ip and then loses it, if added too soon.
	cache.runChecks()
	go cache.run()
	coremain.Run()
	// Unlikely to reach here, if we did it is because coremain exited and the signal was not trapped.
	clog.Errorf("Untrapped signal, tearing down")
	cache.teardownNetworking()
}
<|endoftext|>