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

// This file tests types.Check by using it to
// typecheck the standard library and tests.

package types_test

import (
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	_ "code.google.com/p/go.tools/go/gcimporter"
	. "code.google.com/p/go.tools/go/types"
)

var (
	pkgCount int // number of packages processed
	start    = time.Now()
)

func TestStdlib(t *testing.T) {
	walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg"))
	if testing.Verbose() {
		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
	}
}

// firstComment returns the contents of the first comment in
// the given file, assuming there's one within the first KB.
func firstComment(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		return ""
	}
	defer f.Close()

	var src [1 << 10]byte // read at most 1KB
	n, _ := f.Read(src[:])

	var s scanner.Scanner
	s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil, scanner.ScanComments)
	for {
		_, tok, lit := s.Scan()
		switch tok {
		case token.COMMENT:
			// remove trailing */ of multi-line comment
			if lit[1] == '*' {
				lit = lit[:len(lit)-2]
			}
			return strings.TrimSpace(lit[2:])
		case token.EOF:
			return ""
		}
	}
}

func testTestDir(t *testing.T, path string, ignore ...string) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		t.Fatal(err)
	}

	excluded := make(map[string]bool)
	for _, filename := range ignore {
		excluded[filename] = true
	}

	fset := token.NewFileSet()
	for _, f := range files {
		// filter directory contents
		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
			continue
		}

		// get per-file instructions
		expectErrors := false
		filename := filepath.Join(path, f.Name())
		if cmd := firstComment(filename); cmd != "" {
			switch cmd {
			case "skip", "compiledir":
				continue // ignore this file
			case "errorcheck":
				expectErrors = true
			}
		}

		// parse and type-check file
		file, err := parser.ParseFile(fset, filename, nil, 0)
		if err == nil {
			_, err = Check(filename, fset, []*ast.File{file})
		}

		if expectErrors {
			if err == nil {
				t.Errorf("expected errors but found none in %s", filename)
			}
		} else {
			if err != nil {
				t.Error(err)
			}
		}
	}
}

func TestStdTest(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
		"cmplxdivide.go",          // also needs file cmplxdivide1.go - ignore
		"mapnan.go", "sigchld.go", // don't work on Windows; testTestDir should consult build tags
	)
}

func TestStdFixed(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
		"bug459.go",    // likely incorrect test - see issue 6793 (pending spec clarification)
		"issue3924.go", // likely incorrect test - see issue 6671 (pending spec clarification)
	)
}

func TestStdKen(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken"))
}

// Package paths of excluded packages.
var excluded = map[string]bool{
	"builtin": true,
}

// typecheck typechecks the given package files.
func typecheck(t *testing.T, path string, filenames []string) {
	fset := token.NewFileSet()

	// parse package files
	var files []*ast.File
	for _, filename := range filenames {
		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
		if err != nil {
			// the parser error may be a list of individual errors; report them all
			if list, ok := err.(scanner.ErrorList); ok {
				for _, err := range list {
					t.Error(err)
				}
				return
			}
			t.Error(err)
			return
		}

		if testing.Verbose() {
			if len(files) == 0 {
				fmt.Println("package", file.Name.Name)
			}
			fmt.Println("\t", filename)
		}

		files = append(files, file)
	}

	// typecheck package files
	var conf Config
	conf.Error = func(err error) { t.Error(err) }
	conf.Check(path, fset, files, nil)
	pkgCount++
}

// pkgFilenames returns the list of package filenames for the given directory.
func pkgFilenames(dir string) ([]string, error) {
	ctxt := build.Default
	ctxt.CgoEnabled = false
	pkg, err := ctxt.ImportDir(dir, 0)
	if err != nil {
		if _, nogo := err.(*build.NoGoError); nogo {
			return nil, nil // no *.go files, not an error
		}
		return nil, err
	}
	if excluded[pkg.ImportPath] {
		return nil, nil
	}
	var filenames []string
	for _, name := range pkg.GoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	for _, name := range pkg.TestGoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	return filenames, nil
}

// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
//       necessarily be shorter or clearer after adding the code to
//       terminate early for -short tests.

func walkDirs(t *testing.T, dir string) {
	// limit run time for short tests
	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
		return
	}

	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Error(err)
		return
	}

	// typecheck package in directory
	files, err := pkgFilenames(dir)
	if err != nil {
		t.Error(err)
		return
	}
	if files != nil {
		typecheck(t, dir, files)
	}

	// traverse subdirectories, but don't walk into testdata
	for _, fi := range fis {
		if fi.IsDir() && fi.Name() != "testdata" {
			walkDirs(t, filepath.Join(dir, fi.Name()))
		}
	}
}
<commit_msg>go.tools/go/types: correct a comment (was pointing at wrong issue)<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file tests types.Check by using it to
// typecheck the standard library and tests.

package types_test

import (
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	_ "code.google.com/p/go.tools/go/gcimporter"
	. "code.google.com/p/go.tools/go/types"
)

var (
	pkgCount int // number of packages processed
	start    = time.Now()
)

func TestStdlib(t *testing.T) {
	walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg"))
	if testing.Verbose() {
		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
	}
}

// firstComment returns the contents of the first comment in
// the given file, assuming there's one within the first KB.
func firstComment(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		return ""
	}
	defer f.Close()

	var src [1 << 10]byte // read at most 1KB
	n, _ := f.Read(src[:])

	var s scanner.Scanner
	s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil, scanner.ScanComments)
	for {
		_, tok, lit := s.Scan()
		switch tok {
		case token.COMMENT:
			// remove trailing */ of multi-line comment
			if lit[1] == '*' {
				lit = lit[:len(lit)-2]
			}
			return strings.TrimSpace(lit[2:])
		case token.EOF:
			return ""
		}
	}
}

func testTestDir(t *testing.T, path string, ignore ...string) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		t.Fatal(err)
	}

	excluded := make(map[string]bool)
	for _, filename := range ignore {
		excluded[filename] = true
	}

	fset := token.NewFileSet()
	for _, f := range files {
		// filter directory contents
		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
			continue
		}

		// get per-file instructions
		expectErrors := false
		filename := filepath.Join(path, f.Name())
		if cmd := firstComment(filename); cmd != "" {
			switch cmd {
			case "skip", "compiledir":
				continue // ignore this file
			case "errorcheck":
				expectErrors = true
			}
		}

		// parse and type-check file
		file, err := parser.ParseFile(fset, filename, nil, 0)
		if err == nil {
			_, err = Check(filename, fset, []*ast.File{file})
		}

		if expectErrors {
			if err == nil {
				t.Errorf("expected errors but found none in %s", filename)
			}
		} else {
			if err != nil {
				t.Error(err)
			}
		}
	}
}

func TestStdTest(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
		"cmplxdivide.go",          // also needs file cmplxdivide1.go - ignore
		"mapnan.go", "sigchld.go", // don't work on Windows; testTestDir should consult build tags
	)
}

func TestStdFixed(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
		"bug459.go",    // likely incorrect test - see issue 6703 (pending spec clarification)
		"issue3924.go", // likely incorrect test - see issue 6671 (pending spec clarification)
	)
}

func TestStdKen(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken"))
}

// Package paths of excluded packages.
var excluded = map[string]bool{
	"builtin": true,
}

// typecheck typechecks the given package files.
func typecheck(t *testing.T, path string, filenames []string) {
	fset := token.NewFileSet()

	// parse package files
	var files []*ast.File
	for _, filename := range filenames {
		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
		if err != nil {
			// the parser error may be a list of individual errors; report them all
			if list, ok := err.(scanner.ErrorList); ok {
				for _, err := range list {
					t.Error(err)
				}
				return
			}
			t.Error(err)
			return
		}

		if testing.Verbose() {
			if len(files) == 0 {
				fmt.Println("package", file.Name.Name)
			}
			fmt.Println("\t", filename)
		}

		files = append(files, file)
	}

	// typecheck package files
	var conf Config
	conf.Error = func(err error) { t.Error(err) }
	conf.Check(path, fset, files, nil)
	pkgCount++
}

// pkgFilenames returns the list of package filenames for the given directory.
func pkgFilenames(dir string) ([]string, error) {
	ctxt := build.Default
	ctxt.CgoEnabled = false
	pkg, err := ctxt.ImportDir(dir, 0)
	if err != nil {
		if _, nogo := err.(*build.NoGoError); nogo {
			return nil, nil // no *.go files, not an error
		}
		return nil, err
	}
	if excluded[pkg.ImportPath] {
		return nil, nil
	}
	var filenames []string
	for _, name := range pkg.GoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	for _, name := range pkg.TestGoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	return filenames, nil
}

// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
//       necessarily be shorter or clearer after adding the code to
//       terminate early for -short tests.

func walkDirs(t *testing.T, dir string) {
	// limit run time for short tests
	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
		return
	}

	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Error(err)
		return
	}

	// typecheck package in directory
	files, err := pkgFilenames(dir)
	if err != nil {
		t.Error(err)
		return
	}
	if files != nil {
		typecheck(t, dir, files)
	}

	// traverse subdirectories, but don't walk into testdata
	for _, fi := range fis {
		if fi.IsDir() && fi.Name() != "testdata" {
			walkDirs(t, filepath.Join(dir, fi.Name()))
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2014 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.
*/

// kube2consul is a bridge between Kubernetes and Consul.  It watches the
// Kubernetes master for changes in Services and creates new DNS records on the
// consul agent.

package main // import "github.com/jmccarty3/kube2consul"

import (
	"flag"
	"fmt"
	"net/url"
	"os"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/golang/glog"
	consulapi "github.com/hashicorp/consul/api"
	kapi "k8s.io/kubernetes/pkg/api"
	kcache "k8s.io/kubernetes/pkg/client/cache"
	kclient "k8s.io/kubernetes/pkg/client/unversioned"
	kclientcmd "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	kcontrollerFramework "k8s.io/kubernetes/pkg/controller/framework"
	kframework "k8s.io/kubernetes/pkg/controller/framework"
	kSelector "k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/util"

	//  "k8s.io/kubernetes/pkg/api"
	//  "k8s.io/kubernetes/pkg/fields"
	//  "k8s.io/kubernetes/pkg/labels"
)

var (
	argConsulAgent   = flag.String("consul-agent", "http://127.0.0.1:8500", "URL to consul agent")
	argKubecfgFile   = flag.String("kubecfg_file", "", "Location of kubecfg file for access to kubernetes service")
	argKubeMasterUrl = flag.String("kube_master_url", "https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}", "Url to reach kubernetes master. Env variables in this flag will be expanded.")
	argDryRun        = flag.Bool("dryrun", false, "Runs without connecting to consul")
)

const (
	// Maximum number of attempts to connect to consul server.
	maxConnectAttempts = 12
	// Resync period for the kube controller loop.
	resyncPeriod = 5 * time.Second
)

type nodeInformation struct {
	name string

	address string

	ready bool
	// map[service] DNS IDs
	ids map[string][]string
}

type kube2consul struct {
	// Consul client.
	consulClient *consulapi.Client

	// DNS domain name.
	domain string

	//Nodes Name / valid
	nodes map[string]nodeInformation

	//All Services.
	services map[string]*kapi.Service
}

func Newkube2consul() *kube2consul {
	var k kube2consul
	k.nodes = make(map[string]nodeInformation)
	k.services = make(map[string]*kapi.Service)

	return &k
}

func NewnodeInformation() *nodeInformation {
	var n nodeInformation
	n.ready = false
	n.ids = make(map[string][]string)

	return &n
}

func Contains(s []string, e string) bool {
	for _, i := range s {
		if i == e {
			return true
		}
	}
	return false
}

func (ks *kube2consul) removeDNS(recordID string) error {
	glog.Infof("Removing %s from DNS", recordID)
	if ks.consulClient != nil {
		ks.consulClient.Agent().ServiceDeregister(recordID)
	}
	return nil
}

func (ks *kube2consul) createDNS(record string, service *kapi.Service, node *nodeInformation) error {
	if strings.Contains(record, ".") {
		glog.Infof("Service names containing '.' are not supported: %s\n", service.Name)
		return nil
	}

	// if ClusterIP is not set, do not create a DNS records
	if !kapi.IsServiceIPSet(service) {
		glog.Infof("Skipping dns record for headless service: %s\n", service.Name)
		return nil
	}

	//Currently this is only for NodePorts.
	if service.Spec.Type != kapi.ServiceTypeNodePort {
		glog.V(3).Infof("Skipping non-NodePort service: %s\n", service.Name)
		return nil
	}

	for i := range service.Spec.Ports {
		newId := node.name + record + service.Spec.Ports[i].Name
		var asrName string

		//If the port has a name. Use that.
		if len(service.Spec.Ports[i].Name) > 0 {
			asrName = record + "-" + service.Spec.Ports[i].Name
		} else if len(service.Spec.Ports) == 1 { //TODO: Pull out logic later
			asrName = record
		} else {
			asrName = record + "-" + strconv.Itoa(service.Spec.Ports[i].Port)
		}

		asr := &consulapi.AgentServiceRegistration{
			ID:      newId,
			Name:    asrName,
			Address: node.address,
			Port:    service.Spec.Ports[i].NodePort,
			Tags:    []string{"Kube"},
		}

		if Contains(node.ids[record], newId) == false {
			glog.Infof("Setting DNS record: %v -> %v:%d\n", asr.Name, asr.Address, asr.Port)

			if ks.consulClient != nil {
				if err := ks.consulClient.Agent().ServiceRegister(asr); err != nil {
					return err
				}
			}

			node.ids[record] = append(node.ids[record], newId)
		}
	}
	return nil
}

func newConsulClient(consulAgent string) (*consulapi.Client, error) {
	var (
		client *consulapi.Client
		err    error
	)

	consulConfig := consulapi.DefaultConfig()
	consulAgentUrl, err := url.Parse(consulAgent)
	if err != nil {
		glog.Infof("Error parsing Consul url")
		return nil, err
	}

	if consulAgentUrl.Host != "" {
		consulConfig.Address = consulAgentUrl.Host
	}

	if consulAgentUrl.Scheme != "" {
		consulConfig.Scheme = consulAgentUrl.Scheme
	}

	client, err = consulapi.NewClient(consulConfig)
	if err != nil {
		glog.Infof("Error creating Consul client")
		return nil, err
	}

	for attempt := 1; attempt <= maxConnectAttempts; attempt++ {
		if _, err = client.Agent().Self(); err == nil {
			break
		}

		if attempt == maxConnectAttempts {
			break
		}

		glog.Infof("[Attempt: %d] Attempting access to Consul after 5 second sleep", attempt)
		time.Sleep(5 * time.Second)
	}

	if err != nil {
		return nil, fmt.Errorf("failed to connect to Consul agent: %v, error: %v", consulAgent, err)
	}
	glog.Infof("Consul agent found: %v", consulAgent)

	return client, nil
}

func getKubeMasterUrl() (string, error) {
	if *argKubeMasterUrl == "" {
		return "", fmt.Errorf("no --kube_master_url specified")
	}
	parsedUrl, err := url.Parse(os.ExpandEnv(*argKubeMasterUrl))
	if err != nil {
		return "", fmt.Errorf("failed to parse --kube_master_url %s - %v", *argKubeMasterUrl, err)
	}
	if parsedUrl.Scheme == "" || parsedUrl.Host == "" || parsedUrl.Host == ":" {
		return "", fmt.Errorf("invalid --kube_master_url specified %s", *argKubeMasterUrl)
	}
	return parsedUrl.String(), nil
}

// TODO: evaluate using pkg/client/clientcmd
func newKubeClient() (*kclient.Client, error) {
	var config *kclient.Config
	masterUrl, err := getKubeMasterUrl()
	if err != nil {
		return nil, err
	}
	if *argKubecfgFile == "" {
		config = &kclient.Config{
			Host:    masterUrl,
			Version: "v1",
		}
	} else {
		var err error
		overrides := &kclientcmd.ConfigOverrides{}
		overrides.ClusterInfo.Server = masterUrl                                     // might be "", but that is OK
		rules := &kclientcmd.ClientConfigLoadingRules{ExplicitPath: *argKubecfgFile} // might be "", but that is OK
		if config, err = kclientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig(); err != nil {
			return nil, err
		}
	}
	glog.Infof("Using %s for kubernetes master", config.Host)
	glog.Infof("Using kubernetes API %s", config.Version)
	return kclient.New(config)
}

func buildNameString(service, namespace string) string {
	//glog.Infof("Name String: %s  %s", service, namespace)
	//return fmt.Sprintf("%s.%s", service, namespace)
	return fmt.Sprintf("%s", service)
}

// Returns a cache.ListWatch that gets all changes to services.
func createServiceLW(kubeClient *kclient.Client) *kcache.ListWatch {
	return kcache.NewListWatchFromClient(kubeClient, "services", kapi.NamespaceAll, kSelector.Everything())
}

// Returns a cache.ListWatch that gets all changes to services.
func createNodeLW(kubeClient *kclient.Client) *kcache.ListWatch {
	return kcache.NewListWatchFromClient(kubeClient, "nodes", kapi.NamespaceAll, kSelector.Everything())
}

func (ks *kube2consul) newService(obj interface{}) {
	if s, ok := obj.(*kapi.Service); ok {
		name := buildNameString(s.Name, s.Namespace)
		ks.services[name] = s

		glog.V(2).Info("Creating Service: ", name)
		//Add to all existing nodes
		for _, node := range ks.nodes {
			if node.ready {
				ks.createDNS(name, s, &node)
			}
		}
	}
}

func (ks *kube2consul) removeService(obj interface{}) {
	if s, ok := obj.(*kapi.Service); ok {
		name := buildNameString(s.Name, s.Namespace)
		//Remove service from node
		for _, node := range ks.nodes {
			for _, id := range node.ids[name] {
				ks.removeDNS(id)
			}
			delete(node.ids, name)
		}
		delete(ks.services, name)
	}
}

func (ks *kube2consul) updateService(oldObj, newObj interface{}) {
	if old, ok := oldObj.(*kapi.Service); ok {
		if new, ok := newObj.(*kapi.Service); ok {
			if reflect.DeepEqual(*old, *new) == false {
				ks.removeService(old)
				ks.newService(new)
			}
		}
	}
}

func (ks *kube2consul) updateNode(oldObj, newObj interface{}) {
	if n, ok := newObj.(*kapi.Node); ok {
		ready := n.Status.Conditions[0].Status == kapi.ConditionTrue
		nodeInfo := ks.nodes[n.Name]

		if nodeInfo.ready != ready {
			nodeInfo.ready = ready
			if ready {
				for serviceName, service := range ks.services {
					ks.createDNS(serviceName, service, &nodeInfo)
				}
			} else {
				for _, serviceIDs := range nodeInfo.ids {
					for _, serviceID := range serviceIDs {
						ks.removeDNS(serviceID)
					}
				}
				nodeInfo.ids = make(map[string][]string) //Clear tha map
			}
		}
	}
}

func (ks *kube2consul) newNode(newObj interface{}) {
	if node, ok := newObj.(*kapi.Node); ok {
		if _, ok := ks.nodes[node.Name]; !ok {
			glog.Info("Adding Node: ", node.Name)
			var newNode = *NewnodeInformation()
			newNode.name = node.Name
			newNode.address = node.Status.Addresses[0].Address

			ks.nodes[node.Name] = newNode
		}
	}
}

func (ks *kube2consul) removeNode(oldObj interface{}) {
	if node, ok := oldObj.(*kapi.Node); ok {
		if info, ok := ks.nodes[node.Name]; ok {
			glog.Info("Removing Node: ", node.Name)
			for _, idSet := range info.ids {
				for _, id := range idSet {
					ks.removeDNS(id)
				}
			}

			delete(ks.nodes, node.Name)
		}
	}
}

func watchForServices(kubeClient *kclient.Client, ks *kube2consul) {
	var serviceController *kcontrollerFramework.Controller
	_, serviceController = kframework.NewInformer(
		createServiceLW(kubeClient),
		&kapi.Service{},
		resyncPeriod,
		kframework.ResourceEventHandlerFuncs{
			AddFunc:    ks.newService,
			DeleteFunc: ks.removeService,
			UpdateFunc: ks.updateService,
		},
	)
	go serviceController.Run(util.NeverStop)
}

func watchForNodes(kubeClient *kclient.Client, ks *kube2consul) kcache.Store {
	store, serviceController := kframework.NewInformer(
		createNodeLW(kubeClient),
		&kapi.Node{},
		resyncPeriod,
		kframework.ResourceEventHandlerFuncs{
			AddFunc:    ks.newNode,
			DeleteFunc: ks.removeNode,
			UpdateFunc: ks.updateNode,
		},
	)
	glog.Info("About to call run!")
	go serviceController.Run(util.NeverStop)
	return store
}

func main() {
	flag.Parse()
	var err error
	// TODO: Validate input flags.
	ks := Newkube2consul()

	if *argDryRun {
		glog.Info("Dryrun started. Ignoring Consul")
	} else {
		if ks.consulClient, err = newConsulClient(*argConsulAgent); err != nil {
			glog.Fatalf("Failed to create Consul client - %v", err)
		}
	}

	kubeClient, err := newKubeClient()
	if err != nil {
		glog.Fatalf("Failed to create a kubernetes client: %v", err)
	}

	glog.Info(kubeClient.ServerVersion())

	watchForServices(kubeClient, ks)
	watchForNodes(kubeClient, ks)
	glog.Info("Watchers running")
	select {}
}
<commit_msg>Adding label for port type<commit_after>/*
Copyright 2014 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.
*/

// kube2consul is a bridge between Kubernetes and Consul.  It watches the
// Kubernetes master for changes in Services and creates new DNS records on the
// consul agent.

package main // import "github.com/jmccarty3/kube2consul"

import (
	"flag"
	"fmt"
	"net/url"
	"os"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/golang/glog"
	consulapi "github.com/hashicorp/consul/api"
	kapi "k8s.io/kubernetes/pkg/api"
	kcache "k8s.io/kubernetes/pkg/client/cache"
	kclient "k8s.io/kubernetes/pkg/client/unversioned"
	kclientcmd "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
	kcontrollerFramework "k8s.io/kubernetes/pkg/controller/framework"
	kframework "k8s.io/kubernetes/pkg/controller/framework"
	kSelector "k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/util"

	//  "k8s.io/kubernetes/pkg/api"
	//  "k8s.io/kubernetes/pkg/fields"
	//  "k8s.io/kubernetes/pkg/labels"
)

var (
	argConsulAgent   = flag.String("consul-agent", "http://127.0.0.1:8500", "URL to consul agent")
	argKubecfgFile   = flag.String("kubecfg_file", "", "Location of kubecfg file for access to kubernetes service")
	argKubeMasterUrl = flag.String("kube_master_url", "https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}", "Url to reach kubernetes master. Env variables in this flag will be expanded.")
	argDryRun        = flag.Bool("dryrun", false, "Runs without connecting to consul")
)

const (
	// Maximum number of attempts to connect to consul server.
	maxConnectAttempts = 12
	// Resync period for the kube controller loop.
	resyncPeriod = 5 * time.Second
)

type nodeInformation struct {
	name string

	address string

	ready bool
	// map[service] DNS IDs
	ids map[string][]string
}

type kube2consul struct {
	// Consul client.
	consulClient *consulapi.Client

	// DNS domain name.
	domain string

	//Nodes Name / valid
	nodes map[string]nodeInformation

	//All Services.
	services map[string]*kapi.Service
}

func Newkube2consul() *kube2consul {
	var k kube2consul
	k.nodes = make(map[string]nodeInformation)
	k.services = make(map[string]*kapi.Service)

	return &k
}

func NewnodeInformation() *nodeInformation {
	var n nodeInformation
	n.ready = false
	n.ids = make(map[string][]string)

	return &n
}

func Contains(s []string, e string) bool {
	for _, i := range s {
		if i == e {
			return true
		}
	}
	return false
}

func (ks *kube2consul) removeDNS(recordID string) error {
	glog.Infof("Removing %s from DNS", recordID)
	if ks.consulClient != nil {
		ks.consulClient.Agent().ServiceDeregister(recordID)
	}
	return nil
}

func (ks *kube2consul) createDNS(record string, service *kapi.Service, node *nodeInformation) error {
	if strings.Contains(record, ".") {
		glog.Infof("Service names containing '.' are not supported: %s\n", service.Name)
		return nil
	}

	// if ClusterIP is not set, do not create a DNS records
	if !kapi.IsServiceIPSet(service) {
		glog.Infof("Skipping dns record for headless service: %s\n", service.Name)
		return nil
	}

	//Currently this is only for NodePorts.
	if service.Spec.Type != kapi.ServiceTypeNodePort {
		glog.V(3).Infof("Skipping non-NodePort service: %s\n", service.Name)
		return nil
	}

	for i := range service.Spec.Ports {
		newId := node.name + record + service.Spec.Ports[i].Name
		var asrName string

		//If the port has a name. Use that.
		if len(service.Spec.Ports[i].Name) > 0 {
			asrName = record + "-" + service.Spec.Ports[i].Name
		} else if len(service.Spec.Ports) == 1 { //TODO: Pull out logic later
			asrName = record
		} else {
			asrName = record + "-" + strconv.Itoa(service.Spec.Ports[i].Port)
		}

		asr := &consulapi.AgentServiceRegistration{
			ID:      newId,
			Name:    asrName,
			Address: node.address,
			Port:    service.Spec.Ports[i].NodePort,
			Tags:    []string{"Kube", service.Spec.Ports[i].Protocol},
		}

		if Contains(node.ids[record], newId) == false {
			glog.Infof("Setting DNS record: %v -> %v:%d\n", asr.Name, asr.Address, asr.Port)

			if ks.consulClient != nil {
				if err := ks.consulClient.Agent().ServiceRegister(asr); err != nil {
					return err
				}
			}

			node.ids[record] = append(node.ids[record], newId)
		}
	}
	return nil
}

func newConsulClient(consulAgent string) (*consulapi.Client, error) {
	var (
		client *consulapi.Client
		err    error
	)

	consulConfig := consulapi.DefaultConfig()
	consulAgentUrl, err := url.Parse(consulAgent)
	if err != nil {
		glog.Infof("Error parsing Consul url")
		return nil, err
	}

	if consulAgentUrl.Host != "" {
		consulConfig.Address = consulAgentUrl.Host
	}

	if consulAgentUrl.Scheme != "" {
		consulConfig.Scheme = consulAgentUrl.Scheme
	}

	client, err = consulapi.NewClient(consulConfig)
	if err != nil {
		glog.Infof("Error creating Consul client")
		return nil, err
	}

	for attempt := 1; attempt <= maxConnectAttempts; attempt++ {
		if _, err = client.Agent().Self(); err == nil {
			break
		}

		if attempt == maxConnectAttempts {
			break
		}

		glog.Infof("[Attempt: %d] Attempting access to Consul after 5 second sleep", attempt)
		time.Sleep(5 * time.Second)
	}

	if err != nil {
		return nil, fmt.Errorf("failed to connect to Consul agent: %v, error: %v", consulAgent, err)
	}
	glog.Infof("Consul agent found: %v", consulAgent)

	return client, nil
}

func getKubeMasterUrl() (string, error) {
	if *argKubeMasterUrl == "" {
		return "", fmt.Errorf("no --kube_master_url specified")
	}
	parsedUrl, err := url.Parse(os.ExpandEnv(*argKubeMasterUrl))
	if err != nil {
		return "", fmt.Errorf("failed to parse --kube_master_url %s - %v", *argKubeMasterUrl, err)
	}
	if parsedUrl.Scheme == "" || parsedUrl.Host == "" || parsedUrl.Host == ":" {
		return "", fmt.Errorf("invalid --kube_master_url specified %s", *argKubeMasterUrl)
	}
	return parsedUrl.String(), nil
}

// TODO: evaluate using pkg/client/clientcmd
func newKubeClient() (*kclient.Client, error) {
	var config *kclient.Config
	masterUrl, err := getKubeMasterUrl()
	if err != nil {
		return nil, err
	}
	if *argKubecfgFile == "" {
		config = &kclient.Config{
			Host:    masterUrl,
			Version: "v1",
		}
	} else {
		var err error
		overrides := &kclientcmd.ConfigOverrides{}
		overrides.ClusterInfo.Server = masterUrl                                     // might be "", but that is OK
		rules := &kclientcmd.ClientConfigLoadingRules{ExplicitPath: *argKubecfgFile} // might be "", but that is OK
		if config, err = kclientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig(); err != nil {
			return nil, err
		}
	}
	glog.Infof("Using %s for kubernetes master", config.Host)
	glog.Infof("Using kubernetes API %s", config.Version)
	return kclient.New(config)
}

func buildNameString(service, namespace string) string {
	//glog.Infof("Name String: %s  %s", service, namespace)
	//return fmt.Sprintf("%s.%s", service, namespace)
	return fmt.Sprintf("%s", service)
}

// Returns a cache.ListWatch that gets all changes to services.
func createServiceLW(kubeClient *kclient.Client) *kcache.ListWatch {
	return kcache.NewListWatchFromClient(kubeClient, "services", kapi.NamespaceAll, kSelector.Everything())
}

// Returns a cache.ListWatch that gets all changes to services.
func createNodeLW(kubeClient *kclient.Client) *kcache.ListWatch {
	return kcache.NewListWatchFromClient(kubeClient, "nodes", kapi.NamespaceAll, kSelector.Everything())
}

func (ks *kube2consul) newService(obj interface{}) {
	if s, ok := obj.(*kapi.Service); ok {
		name := buildNameString(s.Name, s.Namespace)
		ks.services[name] = s

		glog.V(2).Info("Creating Service: ", name)
		//Add to all existing nodes
		for _, node := range ks.nodes {
			if node.ready {
				ks.createDNS(name, s, &node)
			}
		}
	}
}

func (ks *kube2consul) removeService(obj interface{}) {
	if s, ok := obj.(*kapi.Service); ok {
		name := buildNameString(s.Name, s.Namespace)
		//Remove service from node
		for _, node := range ks.nodes {
			for _, id := range node.ids[name] {
				ks.removeDNS(id)
			}
			delete(node.ids, name)
		}
		delete(ks.services, name)
	}
}

func (ks *kube2consul) updateService(oldObj, newObj interface{}) {
	if old, ok := oldObj.(*kapi.Service); ok {
		if new, ok := newObj.(*kapi.Service); ok {
			if reflect.DeepEqual(*old, *new) == false {
				ks.removeService(old)
				ks.newService(new)
			}
		}
	}
}

func (ks *kube2consul) updateNode(oldObj, newObj interface{}) {
	if n, ok := newObj.(*kapi.Node); ok {
		ready := n.Status.Conditions[0].Status == kapi.ConditionTrue
		nodeInfo := ks.nodes[n.Name]

		if nodeInfo.ready != ready {
			nodeInfo.ready = ready
			if ready {
				for serviceName, service := range ks.services {
					ks.createDNS(serviceName, service, &nodeInfo)
				}
			} else {
				for _, serviceIDs := range nodeInfo.ids {
					for _, serviceID := range serviceIDs {
						ks.removeDNS(serviceID)
					}
				}
				nodeInfo.ids = make(map[string][]string) //Clear tha map
			}
		}
	}
}

func (ks *kube2consul) newNode(newObj interface{}) {
	if node, ok := newObj.(*kapi.Node); ok {
		if _, ok := ks.nodes[node.Name]; !ok {
			glog.Info("Adding Node: ", node.Name)
			var newNode = *NewnodeInformation()
			newNode.name = node.Name
			newNode.address = node.Status.Addresses[0].Address

			ks.nodes[node.Name] = newNode
		}
	}
}

func (ks *kube2consul) removeNode(oldObj interface{}) {
	if node, ok := oldObj.(*kapi.Node); ok {
		if info, ok := ks.nodes[node.Name]; ok {
			glog.Info("Removing Node: ", node.Name)
			for _, idSet := range info.ids {
				for _, id := range idSet {
					ks.removeDNS(id)
				}
			}

			delete(ks.nodes, node.Name)
		}
	}
}

func watchForServices(kubeClient *kclient.Client, ks *kube2consul) {
	var serviceController *kcontrollerFramework.Controller
	_, serviceController = kframework.NewInformer(
		createServiceLW(kubeClient),
		&kapi.Service{},
		resyncPeriod,
		kframework.ResourceEventHandlerFuncs{
			AddFunc:    ks.newService,
			DeleteFunc: ks.removeService,
			UpdateFunc: ks.updateService,
		},
	)
	go serviceController.Run(util.NeverStop)
}

func watchForNodes(kubeClient *kclient.Client, ks *kube2consul) kcache.Store {
	store, serviceController := kframework.NewInformer(
		createNodeLW(kubeClient),
		&kapi.Node{},
		resyncPeriod,
		kframework.ResourceEventHandlerFuncs{
			AddFunc:    ks.newNode,
			DeleteFunc: ks.removeNode,
			UpdateFunc: ks.updateNode,
		},
	)
	glog.Info("About to call run!")
	go serviceController.Run(util.NeverStop)
	return store
}

func main() {
	flag.Parse()
	var err error
	// TODO: Validate input flags.
	ks := Newkube2consul()

	if *argDryRun {
		glog.Info("Dryrun started. Ignoring Consul")
	} else {
		if ks.consulClient, err = newConsulClient(*argConsulAgent); err != nil {
			glog.Fatalf("Failed to create Consul client - %v", err)
		}
	}

	kubeClient, err := newKubeClient()
	if err != nil {
		glog.Fatalf("Failed to create a kubernetes client: %v", err)
	}

	glog.Info(kubeClient.ServerVersion())

	watchForServices(kubeClient, ks)
	watchForNodes(kubeClient, ks)
	glog.Info("Watchers running")
	select {}
}
<|endoftext|>


<commit_before>// Package ast implements the abstract syntax tree node type.
package ast

import (
	"github.com/saicheems/symtable"
	"github.com/saicheems/token"
)

const (
	Program         = iota // The parent node.
	Block                  // Contains a set of statements.
	Const                  // ex. CONST a = 3, b = 4;
	Var                    // ex. VAR a, b;
	ProcedureParent        // Contains a set of procedure nodes.
	Procedure              // ex. PROCEDURE a; BLOCK
	Call                   // ex. CALL a;
	Begin                  // ex. BEGIN stmt END;
	IfThen                 // ex. IF cond THEN stmt;
	WhileDo                // ex. WHILE cond DO stmt;
	Odd                    // ex. ODD expr;
	Cond                   // ex. a == b; x # y;
	Math                   // Forms mathematical expressions.
	Assignment             // ex. a := 3;
	Terminal               // Contains a identifier token or an integer token.
)

// Represents a single node of the abstract syntax tree.
type Node struct {
	Tag      int                   // One of the constants defined by the package.
	Op       int                   // An operation: +, -, *, /, =, #, ...
	Tok      *token.Token          // Token for terminal nodes.
	Sym      *symtable.SymbolTable // Symbol table that encloses scope of this Node's children.
	Children []*Node               // Contains all children of this node.
}

// newNode returns a new Node. The argument is a tag set to one of the constants defined by the
// package..
func NewNode(t int) *Node {
	node := new(Node)
	node.Tag = t
	node.Children = make([]*Node, 0) // Initialize the children as an empty array.
	return node
}

// appendNode Appends a Node to the children of the Node it is called on.
func (n *Node) AppendNode(node ...*Node) {
	n.Children = append(n.Children, node...)
}

// NewProgramNode returns a new program Node given a block Node.
func NewProgramNode(block *Node) *Node {
	node := NewNode(Program)
	node.AppendNode(block)
	return node
}

// NewBlockNode returns a new block Node given const, var, procedure and statement nodes.
func NewBlockNode(cons *Node, vars *Node, proc *Node, stmt *Node) *Node {
	node := NewNode(Block)
	node.AppendNode(cons, vars, proc, stmt)
	return node
}

// NewConstNode returns a new const Node.
func NewConstNode() *Node {
	node := NewNode(Const)
	return node
}

// NewVarNode returns a new var node.
func NewVarNode() *Node {
	node := NewNode(Var)
	return node
}

// NewProcedureParentNode returns a new procedure parent Node. The procedure parent Node should
// enclose a set of procedure Nodes.
func NewProcedureParentNode() *Node {
	node := NewNode(ProcedureParent)
	return node
}

// NewProcedureNode Returns a new procedure Node given a terminal Node and a block Node.
func NewProcedureNode(iden *Node, bloc *Node) *Node {
	node := NewNode(Procedure)
	node.AppendNode(iden, bloc)
	return node
}

// NewCallNode returns a new call Node given a terminal Node.
func NewCallNode(iden *Node) *Node {
	node := NewNode(Call)
	node.AppendNode(iden)
	return node
}

// NewBeginNode returns a new begin node.
func NewBeginNode() *Node {
	node := NewNode(Begin)
	return node
}

// NewIfThenNode returns a new if then Node given a condition Node and a statement Node.
func NewIfThenNode(cond *Node, stmt *Node) *Node {
	node := NewNode(IfThen)
	node.AppendNode(cond, stmt)
	return node
}

// NewWhileDoNode returns a new while do node given a condition Node and a statement Node.
func NewWhileDoNode(cond *Node, stmt *Node) *Node {
	node := NewNode(WhileDo)
	node.AppendNode(cond, stmt)
	return node
}

// NewOddNode returns a new odd Node given an expression Node.
func NewOddNode(expr *Node) *Node {
	node := NewNode(Odd)
	node.AppendNode(expr)
	return node
}

// NewMathNode returns a new math node given an operation, a left hand expression Node and a right
// hand expression Node.
func NewMathNode(op int, left *Node, right *Node) *Node {
	node := NewNode(Math)
	node.Op = op
	node.AppendNode(left, right)
	return node
}

// NewCondNode returns a new condition node given an operation, a left hand epression Node and a
// right hand expression Node.
func NewCondNode(op int, left *Node, right *Node) *Node {
	node := NewNode(Cond)
	node.Op = op
	node.AppendNode(left, right)
	return node
}

// NewAssignmentNode returns a new assignment node given a left hand terminal Node and a right hand
// expression Node.
func NewAssignmentNode(left *Node, right *Node) *Node {
	node := NewNode(Assignment)
	node.AppendNode(left, right)
	return node
}

// NewTerminalNode returns a new terminal node given a terminal Token (Identifier or Integer).
func NewTerminalNode(tok *token.Token) *Node {
	node := NewNode(Terminal)
	node.Tok = tok
	return node
}
<commit_msg>Capitalized some nodes...<commit_after>// Package ast implements the abstract syntax tree node type.
package ast

import (
	"github.com/saicheems/symtable"
	"github.com/saicheems/token"
)

const (
	Program         = iota // The parent node.
	Block                  // Contains a set of statements.
	Const                  // ex. CONST a = 3, b = 4;
	Var                    // ex. VAR a, b;
	ProcedureParent        // Contains a set of procedure nodes.
	Procedure              // ex. PROCEDURE a; BLOCK
	Call                   // ex. CALL a;
	Begin                  // ex. BEGIN stmt END;
	IfThen                 // ex. IF cond THEN stmt;
	WhileDo                // ex. WHILE cond DO stmt;
	Odd                    // ex. ODD expr;
	Cond                   // ex. a == b; x # y;
	Math                   // Forms mathematical expressions.
	Assignment             // ex. a := 3;
	Terminal               // Contains a identifier token or an integer token.
)

// Represents a single node of the abstract syntax tree.
type Node struct {
	Tag      int                   // One of the constants defined by the package.
	Op       int                   // An operation: +, -, *, /, =, #, ...
	Tok      *token.Token          // Token for terminal nodes.
	Sym      *symtable.SymbolTable // Symbol table that encloses scope of this Node's children.
	Children []*Node               // Contains all children of this node.
}

// newNode returns a new Node. The argument is a tag set to one of the constants defined by the
// package..
func NewNode(t int) *Node {
	node := new(Node)
	node.Tag = t
	node.Children = make([]*Node, 0) // Initialize the children as an empty array.
	return node
}

// appendNode Appends a Node to the children of the Node it is called on.
func (n *Node) AppendNode(node ...*Node) {
	n.Children = append(n.Children, node...)
}

// NewProgramNode returns a new program Node given a block Node.
func NewProgramNode(block *Node) *Node {
	node := NewNode(Program)
	node.AppendNode(block)
	return node
}

// NewBlockNode returns a new block Node given const, var, procedure and statement Nodes.
func NewBlockNode(cons *Node, vars *Node, proc *Node, stmt *Node) *Node {
	node := NewNode(Block)
	node.AppendNode(cons, vars, proc, stmt)
	return node
}

// NewConstNode returns a new const Node.
func NewConstNode() *Node {
	node := NewNode(Const)
	return node
}

// NewVarNode returns a new var Node.
func NewVarNode() *Node {
	node := NewNode(Var)
	return node
}

// NewProcedureParentNode returns a new procedure parent Node. The procedure parent Node should
// enclose a set of procedure Nodes.
func NewProcedureParentNode() *Node {
	node := NewNode(ProcedureParent)
	return node
}

// NewProcedureNode Returns a new procedure Node given a terminal Node and a block Node.
func NewProcedureNode(iden *Node, bloc *Node) *Node {
	node := NewNode(Procedure)
	node.AppendNode(iden, bloc)
	return node
}

// NewCallNode returns a new call Node given a terminal Node.
func NewCallNode(iden *Node) *Node {
	node := NewNode(Call)
	node.AppendNode(iden)
	return node
}

// NewBeginNode returns a new begin Node.
func NewBeginNode() *Node {
	node := NewNode(Begin)
	return node
}

// NewIfThenNode returns a new if then Node given a condition Node and a statement Node.
func NewIfThenNode(cond *Node, stmt *Node) *Node {
	node := NewNode(IfThen)
	node.AppendNode(cond, stmt)
	return node
}

// NewWhileDoNode returns a new while do Node given a condition Node and a statement Node.
func NewWhileDoNode(cond *Node, stmt *Node) *Node {
	node := NewNode(WhileDo)
	node.AppendNode(cond, stmt)
	return node
}

// NewOddNode returns a new odd Node given an expression Node.
func NewOddNode(expr *Node) *Node {
	node := NewNode(Odd)
	node.AppendNode(expr)
	return node
}

// NewMathNode returns a new math Node given an operation, a left hand expression Node and a right
// hand expression Node.
func NewMathNode(op int, left *Node, right *Node) *Node {
	node := NewNode(Math)
	node.Op = op
	node.AppendNode(left, right)
	return node
}

// NewCondNode returns a new condition Node given an operation, a left hand epression Node and a
// right hand expression Node.
func NewCondNode(op int, left *Node, right *Node) *Node {
	node := NewNode(Cond)
	node.Op = op
	node.AppendNode(left, right)
	return node
}

// NewAssignmentNode returns a new assignment Node given a left hand terminal Node and a right hand
// expression Node.
func NewAssignmentNode(left *Node, right *Node) *Node {
	node := NewNode(Assignment)
	node.AppendNode(left, right)
	return node
}

// NewTerminalNode returns a new terminal Node given a terminal Token (Identifier or Integer).
func NewTerminalNode(tok *token.Token) *Node {
	node := NewNode(Terminal)
	node.Tok = tok
	return node
}
<|endoftext|>


<commit_before>package vsock

import (
	"crypto/tls"
	"net"
	"net/http"

	"github.com/lxc/lxd/shared"
)

func vsockHTTPClient(vsockID int, tlsClientCert string, tlsClientKey string, tlsCA string, tlsServerCert string, insecureSkipVerify bool) (*http.Client, error) {
	client := &http.Client{}

	// Get the TLS configuration
	tlsConfig, err := shared.GetTLSConfigMem(tlsClientCert, tlsClientKey, tlsCA, tlsServerCert, insecureSkipVerify)
	if err != nil {
		return nil, err
	}

	client.Transport = &http.Transport{
		TLSClientConfig: tlsConfig,
		// Setup a VM socket dialer
		Dial: func(network, addr string) (net.Conn, error) {
			conn, err := dial(uint32(vsockID), 8443)
			if err != nil {
				return nil, err
			}

			tlsConn := tls.Client(conn, tlsConfig)

			// Validate the connection
			err = tlsConn.Handshake()
			if err != nil {
				conn.Close()
				return nil, err
			}

			return tlsConn, nil
		},
		DisableKeepAlives: true,
	}

	// Setup redirect policy
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		// Replicate the headers
		req.Header = via[len(via)-1].Header

		return nil
	}

	return client, nil
}
<commit_msg>lxd/vsock: Simplifies HTTPClient<commit_after>package vsock

import (
	"crypto/tls"
	"net"
	"net/http"

	"github.com/lxc/lxd/shared"
)

// HTTPClient provides an HTTP client for using over vsock.
func HTTPClient(vsockID int, tlsClientCert string, tlsClientKey string, tlsServerCert string) (*http.Client, error) {
	client := &http.Client{}

	// Get the TLS configuration.
	// tomp TODO remove insecure skip verify.
	tlsConfig, err := shared.GetTLSConfigMem(tlsClientCert, tlsClientKey, "", tlsServerCert, true)
	if err != nil {
		return nil, err
	}

	client.Transport = &http.Transport{
		TLSClientConfig: tlsConfig,
		// Setup a VM socket dialer.
		Dial: func(network, addr string) (net.Conn, error) {
			conn, err := dial(uint32(vsockID), 8443)
			if err != nil {
				return nil, err
			}

			tlsConn := tls.Client(conn, tlsConfig)

			// Validate the connection.
			err = tlsConn.Handshake()
			if err != nil {
				conn.Close()
				return nil, err
			}

			return tlsConn, nil
		},
		DisableKeepAlives: true,
	}

	// Setup redirect policy.
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		// Replicate the headers.
		req.Header = via[len(via)-1].Header

		return nil
	}

	return client, nil
}
<|endoftext|>


<commit_before>package lzb

import (
	"bytes"
	"testing"
)

func TestInitBuffer(t *testing.T) {
	var b buffer
	const capacity = 30
	initBuffer(&b, capacity)
	if n := b.capacity(); n != capacity {
		t.Fatalf("capacity is %d; want %d", n, capacity)
	}
	if n := b.length(); n != 0 {
		t.Fatalf("length is %d; want %d", n, 0)
	}

}

func TestNewBuffer(t *testing.T) {
	const capacity = 30
	b := newBuffer(capacity)
	if n := b.capacity(); n != capacity {
		t.Fatalf("capacity is %d; want %d", n, capacity)
	}
	if n := b.length(); n != 0 {
		t.Fatalf("length is %d; want %d", n, 0)
	}
}

func TestBuffer_Write(t *testing.T) {
	var b buffer
	const capacity = 25
	initBuffer(&b, capacity)
	p := []byte("0123456789")
	n, err := b.Write(p)
	if err != nil {
		t.Fatalf("b.Write: unexpected error %s", err)
	}
	if n != len(p) {
		t.Fatalf("b.Write returned n=%d; want %d", n, len(p))
	}
	n = b.length()
	if n != len(p) {
		t.Fatalf("b.length is %d; want %d", n, len(p))
	}
	n, err = b.Write(p)
	if err != nil {
		t.Fatalf("b.Write: unexpected error %s", err)
	}
	if n != len(p) {
		t.Fatalf("b.Write returned n=%d; want %d", n, len(p))
	}
	if n = b.length(); n != 20 {
		t.Fatalf("data length %d; want %d", n, 20)
	}
	if !bytes.Equal(b.data[:10], p) {
		t.Fatalf("first 10 byte of data wrong")
	}
	if !bytes.Equal(b.data[10:20], p) {
		t.Fatalf("second batch of 10 bytes data wrong: %q", b.data[10:])
	}
	n, err = b.Write(p)
	if err != nil {
		t.Fatalf("b.Write: unexpected error %s", err)
	}
	if n != len(p) {
		t.Fatalf("b.Write returned n=%d; want %d", n, len(p))
	}
	if b.top != 30 {
		t.Fatalf("b.top is %d; want %d", b.top, 30)
	}
	if b.bottom != 5 {
		t.Fatalf("b.bottom is %d; want %d", b.bottom, 35)
	}
	t.Logf("b.data %q", b.data)
	if !bytes.Equal(b.data[:5], p[5:]) {
		t.Fatalf("b.Write overflow problem: b.data[:5] is %q; want %q",
			b.data[:5], p[5:])
	}
	q := make([]byte, 0, 30)
	for i := 0; i < 3; i++ {
		q = append(q, p...)
	}
	n, err = b.Write(q)
	if err != nil {
		t.Fatalf("b.Write: unexpected error %s", err)
	}
	if n != len(q) {
		t.Fatalf("b.Write returned n=%d; want %d", n, len(q))
	}
	if b.top != 60 {
		t.Fatalf("b.top is %d; want %d", b.top, 60)
	}
	if !bytes.Equal(b.data[10:], q[5:20]) {
		t.Fatalf("b.data[:10] is %q; want %q", b.data[:10], q[20:])
	}
	if !bytes.Equal(b.data[:10], q[20:]) {
		t.Fatalf("b.data[:10] is %q; want %q", b.data[:10], q[20:])
	}
	n, err = b.Write([]byte{})
	if err != nil {
		t.Fatalf("b.Write: error %s", err)
	}
	if n != 0 {
		t.Fatalf("b.Write([]byte{}) returned %d; want %d", n, 0)
	}
}

func TestBuffer_Write_limit(t *testing.T) {
	b := newBuffer(20)
	b.writeLimit = 9
	p := []byte("0123456789")
	n, err := b.Write(p)
	if err != errLimit {
		t.Fatalf("b.Write error %s; want %s", err, errLimit)
	}
	if n != 9 {
		t.Fatalf("n after b.Write %d; want %d", n, 9)
	}
	b.writeLimit += 10
	n, err = b.Write(p)
	if err != nil {
		t.Fatalf("b.Write error %s", err)
	}
	if n != 10 {
		t.Fatalf("n after b.Write %d; want %d", n, 10)
	}
}
<commit_msg>lzb: added TestBuffer_WriteByte<commit_after>package lzb

import (
	"bytes"
	"testing"
)

func TestInitBuffer(t *testing.T) {
	var b buffer
	const capacity = 30
	initBuffer(&b, capacity)
	if n := b.capacity(); n != capacity {
		t.Fatalf("capacity is %d; want %d", n, capacity)
	}
	if n := b.length(); n != 0 {
		t.Fatalf("length is %d; want %d", n, 0)
	}

}

func TestNewBuffer(t *testing.T) {
	const capacity = 30
	b := newBuffer(capacity)
	if n := b.capacity(); n != capacity {
		t.Fatalf("capacity is %d; want %d", n, capacity)
	}
	if n := b.length(); n != 0 {
		t.Fatalf("length is %d; want %d", n, 0)
	}
}

func TestBuffer_Write(t *testing.T) {
	var b buffer
	const capacity = 25
	initBuffer(&b, capacity)
	p := []byte("0123456789")
	n, err := b.Write(p)
	if err != nil {
		t.Fatalf("b.Write: unexpected error %s", err)
	}
	if n != len(p) {
		t.Fatalf("b.Write returned n=%d; want %d", n, len(p))
	}
	n = b.length()
	if n != len(p) {
		t.Fatalf("b.length is %d; want %d", n, len(p))
	}
	n, err = b.Write(p)
	if err != nil {
		t.Fatalf("b.Write: unexpected error %s", err)
	}
	if n != len(p) {
		t.Fatalf("b.Write returned n=%d; want %d", n, len(p))
	}
	if n = b.length(); n != 20 {
		t.Fatalf("data length %d; want %d", n, 20)
	}
	if !bytes.Equal(b.data[:10], p) {
		t.Fatalf("first 10 byte of data wrong")
	}
	if !bytes.Equal(b.data[10:20], p) {
		t.Fatalf("second batch of 10 bytes data wrong: %q", b.data[10:])
	}
	n, err = b.Write(p)
	if err != nil {
		t.Fatalf("b.Write: unexpected error %s", err)
	}
	if n != len(p) {
		t.Fatalf("b.Write returned n=%d; want %d", n, len(p))
	}
	if b.top != 30 {
		t.Fatalf("b.top is %d; want %d", b.top, 30)
	}
	if b.bottom != 5 {
		t.Fatalf("b.bottom is %d; want %d", b.bottom, 35)
	}
	t.Logf("b.data %q", b.data)
	if !bytes.Equal(b.data[:5], p[5:]) {
		t.Fatalf("b.Write overflow problem: b.data[:5] is %q; want %q",
			b.data[:5], p[5:])
	}
	q := make([]byte, 0, 30)
	for i := 0; i < 3; i++ {
		q = append(q, p...)
	}
	n, err = b.Write(q)
	if err != nil {
		t.Fatalf("b.Write: unexpected error %s", err)
	}
	if n != len(q) {
		t.Fatalf("b.Write returned n=%d; want %d", n, len(q))
	}
	if b.top != 60 {
		t.Fatalf("b.top is %d; want %d", b.top, 60)
	}
	if !bytes.Equal(b.data[10:], q[5:20]) {
		t.Fatalf("b.data[:10] is %q; want %q", b.data[:10], q[20:])
	}
	if !bytes.Equal(b.data[:10], q[20:]) {
		t.Fatalf("b.data[:10] is %q; want %q", b.data[:10], q[20:])
	}
	n, err = b.Write([]byte{})
	if err != nil {
		t.Fatalf("b.Write: error %s", err)
	}
	if n != 0 {
		t.Fatalf("b.Write([]byte{}) returned %d; want %d", n, 0)
	}
}

func TestBuffer_Write_limit(t *testing.T) {
	b := newBuffer(20)
	b.writeLimit = 9
	p := []byte("0123456789")
	n, err := b.Write(p)
	if err != errLimit {
		t.Fatalf("b.Write error %s; want %s", err, errLimit)
	}
	if n != 9 {
		t.Fatalf("n after b.Write %d; want %d", n, 9)
	}
	b.writeLimit += 10
	n, err = b.Write(p)
	if err != nil {
		t.Fatalf("b.Write error %s", err)
	}
	if n != 10 {
		t.Fatalf("n after b.Write %d; want %d", n, 10)
	}
}

func TestBuffer_WriteByte(t *testing.T) {
	b := newBuffer(20)
	b.writeLimit = 2
	var err error
	if err = b.WriteByte(1); err != nil {
		t.Fatalf("b.WriteByte: error %s", err)
	}
	if b.top != 1 {
		t.Fatalf("after WriteByte b.top is %d; want %d", b.top, 1)
	}
	if err = b.WriteByte(1); err != nil {
		t.Fatalf("b.WriteByte: error %s", err)
	}
	if b.top != 2 {
		t.Fatalf("after WriteByte b.top is %d; want %d", b.top, 1)
	}
	if err = b.WriteByte(1); err != errLimit {
		t.Fatalf("b.WriteByte over limit error %#v; expected %#v",
			err, errLimit)
	}
}
<|endoftext|>


<commit_before>package lzma

import (
	"io"

	"github.com/uli-go/xz/lzbase"
)

// Parameters contain all information required to decode or encode an LZMA
// stream.
//
// The DictSize will be limited by MaxInt32 on 32-bit platforms.
type Parameters struct {
	// number of literal context bits
	LC int
	// number of literal position bits
	LP int
	// number of position bits
	PB int
	// size of the dictionary in bytes
	DictSize int64
	// size of uncompressed data in bytes
	Size int64
	// header includes unpacked size
	SizeInHeader bool
	// end-of-stream marker requested
	EOS bool
	// buffer size
	BufferSize int64
}

// Properties returns lc, lp and pb as Properties value.
func (p *Parameters) Properties() lzbase.Properties {
	props, err := lzbase.NewProperties(p.LC, p.LP, p.PB)
	if err != nil {
		panic(err)
	}
	return props
}

// SetProperties sets the LC, LP and PB fields.
func (p *Parameters) SetProperties(props lzbase.Properties) {
	p.LC, p.LP, p.PB = props.LC(), props.LP(), props.PB()
}

// normalizeSize puts the size on a normalized size. If DictSize and BufferSize
// are zero, then it is set to the value in Default. If both size values are
// too small they will set to the minimum size possible. Note that a buffer
// size less then zero will be ignored and will cause an error by
// verifyParameters.
func normalizeSizes(p *Parameters) {
	if p.DictSize == 0 {
		p.DictSize = Default.DictSize
	}
	if p.DictSize < lzbase.MinDictSize {
		p.DictSize = lzbase.MinDictSize
	}
	if p.BufferSize == 0 {
		p.BufferSize = Default.BufferSize
	}
	if 0 <= p.BufferSize && p.BufferSize < lzbase.MinLength {
		p.BufferSize = lzbase.MaxLength
	}
}

// verifyParameters checks parameters for errors.
func verifyParameters(p *Parameters) error {
	if p == nil {
		return newError("parameters must be non-nil")
	}
	if err := lzbase.VerifyProperties(p.LC, p.LP, p.PB); err != nil {
		return err
	}
	if !(lzbase.MinDictSize <= p.DictSize &&
		p.DictSize <= lzbase.MaxDictSize) {
		return newError("DictSize out of range")
	}
	hlen := int(p.DictSize)
	if hlen < 0 {
		return newError("DictSize cannot be converted into int")
	}
	if p.Size < 0 {
		return newError("length must not be negative")
	}
	return nil
}

// Default defines the parameters used by NewWriter.
var Default = Parameters{
	LC:         3,
	LP:         0,
	PB:         2,
	DictSize:   lzbase.MinDictSize,
	BufferSize: 4096,
}

// getUint32LE reads an uint32 integer from a byte slize
func getUint32LE(b []byte) uint32 {
	x := uint32(b[3]) << 24
	x |= uint32(b[2]) << 16
	x |= uint32(b[1]) << 8
	x |= uint32(b[0])
	return x
}

// getUint64LE converts the uint64 value stored as little endian to an uint64
// value.
func getUint64LE(b []byte) uint64 {
	x := uint64(b[7]) << 56
	x |= uint64(b[6]) << 48
	x |= uint64(b[5]) << 40
	x |= uint64(b[4]) << 32
	x |= uint64(b[3]) << 24
	x |= uint64(b[2]) << 16
	x |= uint64(b[1]) << 8
	x |= uint64(b[0])
	return x
}

// putUint32LE puts an uint32 integer into a byte slice that must have at least
// a lenght of 4 bytes.
func putUint32LE(b []byte, x uint32) {
	b[0] = byte(x)
	b[1] = byte(x >> 8)
	b[2] = byte(x >> 16)
	b[3] = byte(x >> 24)
}

// putUint64LE puts the uint64 value into the byte slice as little endian
// value. The byte slice b must have at least place for 8 bytes.
func putUint64LE(b []byte, x uint64) {
	b[0] = byte(x)
	b[1] = byte(x >> 8)
	b[2] = byte(x >> 16)
	b[3] = byte(x >> 24)
	b[4] = byte(x >> 32)
	b[5] = byte(x >> 40)
	b[6] = byte(x >> 48)
	b[7] = byte(x >> 56)
}

// noHeaderLen defines the value of the length field in the LZMA header.
const noHeaderLen uint64 = 1<<64 - 1

// readHeader reads the classic LZMA header.
func readHeader(r io.Reader) (p *Parameters, err error) {
	b := make([]byte, 13)
	_, err = io.ReadFull(r, b)
	if err != nil {
		return nil, err
	}
	p = new(Parameters)
	props := lzbase.Properties(b[0])
	p.LC, p.LP, p.PB = props.LC(), props.LP(), props.PB()
	p.DictSize = int64(getUint32LE(b[1:]))
	u := getUint64LE(b[5:])
	if u == noHeaderLen {
		p.Size = 0
		p.EOS = true
		p.SizeInHeader = false
	} else {
		p.Size = int64(u)
		if p.Size < 0 {
			return nil, newError(
				"unpack length in header not supported by" +
					" int64")
		}
		p.EOS = false
		p.SizeInHeader = true
	}

	normalizeSizes(p)
	return p, nil
}

// writeHeader writes the header for classic LZMA files.
func writeHeader(w io.Writer, p *Parameters) error {
	var err error
	if err = verifyParameters(p); err != nil {
		return err
	}
	b := make([]byte, 13)
	b[0] = byte(p.Properties())
	if p.DictSize > lzbase.MaxDictSize {
		return newError("DictSize exceeds maximum value")
	}
	putUint32LE(b[1:5], uint32(p.DictSize))
	var l uint64
	if p.SizeInHeader {
		l = uint64(p.Size)
	} else {
		l = noHeaderLen
	}
	putUint64LE(b[5:], l)
	_, err = w.Write(b)
	return err
}
<commit_msg>lzma: fixed comment for Properties method of Parameters<commit_after>package lzma

import (
	"io"

	"github.com/uli-go/xz/lzbase"
)

// Parameters contain all information required to decode or encode an LZMA
// stream.
//
// The DictSize will be limited by MaxInt32 on 32-bit platforms.
type Parameters struct {
	// number of literal context bits
	LC int
	// number of literal position bits
	LP int
	// number of position bits
	PB int
	// size of the dictionary in bytes
	DictSize int64
	// size of uncompressed data in bytes
	Size int64
	// header includes unpacked size
	SizeInHeader bool
	// end-of-stream marker requested
	EOS bool
	// buffer size
	BufferSize int64
}

// Properties returns LC, LP and PB as Properties value.
func (p *Parameters) Properties() lzbase.Properties {
	props, err := lzbase.NewProperties(p.LC, p.LP, p.PB)
	if err != nil {
		panic(err)
	}
	return props
}

// SetProperties sets the LC, LP and PB fields.
func (p *Parameters) SetProperties(props lzbase.Properties) {
	p.LC, p.LP, p.PB = props.LC(), props.LP(), props.PB()
}

// normalizeSize puts the size on a normalized size. If DictSize and BufferSize
// are zero, then it is set to the value in Default. If both size values are
// too small they will set to the minimum size possible. Note that a buffer
// size less then zero will be ignored and will cause an error by
// verifyParameters.
func normalizeSizes(p *Parameters) {
	if p.DictSize == 0 {
		p.DictSize = Default.DictSize
	}
	if p.DictSize < lzbase.MinDictSize {
		p.DictSize = lzbase.MinDictSize
	}
	if p.BufferSize == 0 {
		p.BufferSize = Default.BufferSize
	}
	if 0 <= p.BufferSize && p.BufferSize < lzbase.MinLength {
		p.BufferSize = lzbase.MaxLength
	}
}

// verifyParameters checks parameters for errors.
func verifyParameters(p *Parameters) error {
	if p == nil {
		return newError("parameters must be non-nil")
	}
	if err := lzbase.VerifyProperties(p.LC, p.LP, p.PB); err != nil {
		return err
	}
	if !(lzbase.MinDictSize <= p.DictSize &&
		p.DictSize <= lzbase.MaxDictSize) {
		return newError("DictSize out of range")
	}
	hlen := int(p.DictSize)
	if hlen < 0 {
		return newError("DictSize cannot be converted into int")
	}
	if p.Size < 0 {
		return newError("length must not be negative")
	}
	return nil
}

// Default defines the parameters used by NewWriter.
var Default = Parameters{
	LC:         3,
	LP:         0,
	PB:         2,
	DictSize:   lzbase.MinDictSize,
	BufferSize: 4096,
}

// getUint32LE reads an uint32 integer from a byte slize
func getUint32LE(b []byte) uint32 {
	x := uint32(b[3]) << 24
	x |= uint32(b[2]) << 16
	x |= uint32(b[1]) << 8
	x |= uint32(b[0])
	return x
}

// getUint64LE converts the uint64 value stored as little endian to an uint64
// value.
func getUint64LE(b []byte) uint64 {
	x := uint64(b[7]) << 56
	x |= uint64(b[6]) << 48
	x |= uint64(b[5]) << 40
	x |= uint64(b[4]) << 32
	x |= uint64(b[3]) << 24
	x |= uint64(b[2]) << 16
	x |= uint64(b[1]) << 8
	x |= uint64(b[0])
	return x
}

// putUint32LE puts an uint32 integer into a byte slice that must have at least
// a lenght of 4 bytes.
func putUint32LE(b []byte, x uint32) {
	b[0] = byte(x)
	b[1] = byte(x >> 8)
	b[2] = byte(x >> 16)
	b[3] = byte(x >> 24)
}

// putUint64LE puts the uint64 value into the byte slice as little endian
// value. The byte slice b must have at least place for 8 bytes.
func putUint64LE(b []byte, x uint64) {
	b[0] = byte(x)
	b[1] = byte(x >> 8)
	b[2] = byte(x >> 16)
	b[3] = byte(x >> 24)
	b[4] = byte(x >> 32)
	b[5] = byte(x >> 40)
	b[6] = byte(x >> 48)
	b[7] = byte(x >> 56)
}

// noHeaderLen defines the value of the length field in the LZMA header.
const noHeaderLen uint64 = 1<<64 - 1

// readHeader reads the classic LZMA header.
func readHeader(r io.Reader) (p *Parameters, err error) {
	b := make([]byte, 13)
	_, err = io.ReadFull(r, b)
	if err != nil {
		return nil, err
	}
	p = new(Parameters)
	props := lzbase.Properties(b[0])
	p.LC, p.LP, p.PB = props.LC(), props.LP(), props.PB()
	p.DictSize = int64(getUint32LE(b[1:]))
	u := getUint64LE(b[5:])
	if u == noHeaderLen {
		p.Size = 0
		p.EOS = true
		p.SizeInHeader = false
	} else {
		p.Size = int64(u)
		if p.Size < 0 {
			return nil, newError(
				"unpack length in header not supported by" +
					" int64")
		}
		p.EOS = false
		p.SizeInHeader = true
	}

	normalizeSizes(p)
	return p, nil
}

// writeHeader writes the header for classic LZMA files.
func writeHeader(w io.Writer, p *Parameters) error {
	var err error
	if err = verifyParameters(p); err != nil {
		return err
	}
	b := make([]byte, 13)
	b[0] = byte(p.Properties())
	if p.DictSize > lzbase.MaxDictSize {
		return newError("DictSize exceeds maximum value")
	}
	putUint32LE(b[1:5], uint32(p.DictSize))
	var l uint64
	if p.SizeInHeader {
		l = uint64(p.Size)
	} else {
		l = noHeaderLen
	}
	putUint64LE(b[5:], l)
	_, err = w.Write(b)
	return err
}
<|endoftext|>


<commit_before>package verbose

import (
	"fmt"
	"github.com/deis/deis/tests/dockercliutils"
	"github.com/deis/deis/tests/utils"
	"net/http"
	"strings"
	"testing"
	"time"
)

func runDeisRegistryTest(t *testing.T, testSessionUid string) {
	cli, stdout, stdoutPipe := dockercliutils.GetNewClient()
	done := make(chan bool, 1)
	dockercliutils.BuildDockerfile(t, "../", "deis/registry:"+testSessionUid)
	dockercliutils.RunDeisDataTest(t, "--name", "deis-registry-data", "-v", "/data", "deis/base", "/bin/true")
	IPAddress := dockercliutils.GetInspectData(t, "{{ .NetworkSettings.IPAddress }}", "deis-etcd-"+testSessionUid)
	if strings.Contains(IPAddress, "Error") {
		t.Fatalf("worng IP %s", IPAddress)
	}
	done <- true
	go func() {
		<-done
		fmt.Println("inside run container")
		dockercliutils.RunContainer(t, cli, "--name", "deis-registry-"+testSessionUid, "-p", "5000:5000", "-e", "PUBLISH=5000", "-e", "HOST="+IPAddress, "--volumes-from", "deis-registry-data", "deis/registry:"+testSessionUid)
	}()
	time.Sleep(10000 * time.Millisecond)
	dockercliutils.PrintToStdout(t, stdout, stdoutPipe, "Booting")

}

func deisRegistryServiceTest(t *testing.T, testSessionUid string) {
	IPAddress := dockercliutils.GetInspectData(t, "{{ .NetworkSettings.IPAddress }}", "deis-registry-"+testSessionUid)
	if strings.Contains(IPAddress, "Error") {
		t.Fatalf("worng IP %s", IPAddress)
	}
	url := "http://" + IPAddress + ":5000"
	response, err := http.Get(url)
	if err != nil {
		t.Fatalf("Not reachable %s", err)
	}
	fmt.Println(response)
}

func TestBuild(t *testing.T) {

	fmt.Println("1st")
	var testSessionUid = utils.GetnewUuid()
	testSessionUid = "352aea64"
	dockercliutils.RunEtcdTest(t, testSessionUid)
	fmt.Println("2nd")
	t.Logf("starting registry test: %v", testSessionUid)
	fmt.Println("starting registry test")
	runDeisRegistryTest(t, testSessionUid)
	deisRegistryServiceTest(t, testSessionUid)
	dockercliutils.ClearTestSession(t, testSessionUid)

}
<commit_msg>refactor(tests): add etcd and mock utility packages<commit_after>package verbose

import (
	"fmt"
	"github.com/deis/deis/tests/dockercliutils"
	"github.com/deis/deis/tests/etcdutils"
	"github.com/deis/deis/tests/mockserviceutils"
	"github.com/deis/deis/tests/utils"
	"net/http"
	"strings"
	"testing"
	"time"
)

func runDeisControllerTest(t *testing.T, testSessionUid string) {
	cli, stdout, stdoutPipe := dockercliutils.GetNewClient()
	done := make(chan bool, 1)
	dockercliutils.BuildDockerfile(t, "../", "deis/controller:"+testSessionUid)
	//docker run --name deis-controller -p 8000:8000 -e PUBLISH=8000 -e HOST=${COREOS_PRIVATE_IPV4} --volumes-from=deis-logger deis/controller
	IPAddress := "172.17.8.100"
	done <- true
	go func() {
		<-done
		fmt.Println("inside run container")
		dockercliutils.RunContainer(t, cli, "--name", "deis-controller-"+testSessionUid, "-p", "8000:8000", "-e", "PUBLISH=8000", "-e", "HOST="+IPAddress, "deis/controller:"+testSessionUid)
	}()
	time.Sleep(5000 * time.Millisecond)
	dockercliutils.PrintToStdout(t, stdout, stdoutPipe, "Booting")

}

func deisControllerServiceTest(t *testing.T, testSessionUid string) {
	IPAddress := dockercliutils.GetInspectData(t, "{{ .NetworkSettings.IPAddress }}", "deis-controller-"+testSessionUid)
	if strings.Contains(IPAddress, "Error") {
		t.Fatalf("worng IP %s", IPAddress)
	}
	url := "http://" + IPAddress + ":8000"
	response, err := http.Get(url)
	if err != nil {
		t.Fatalf("Not reachable %s", err)
	}
	fmt.Println(response)
}

func TestBuild(t *testing.T) {
	setkeys := []string{"/deis/registry/protocol",
		"deis/registry/host",
		"/deis/registry/port",
		"/deis/cache/host",
		"/deis/cache/port"}
	setdir := []string{"/deis/controller",
		"/deis/cache",
		"/deis/database",
		"/deis/registry",
		"/deis/domains"}
	fmt.Println("1st")
	var testSessionUid = utils.GetnewUuid()
	//testSessionUid := "352aea64"
	dockercliutils.RunEtcdTest(t, testSessionUid)
	fmt.Println("2nd")
	t.Logf("starting controller test: %v", testSessionUid)
	Controllerhandler := etcdutils.InitetcdValues(setdir, setkeys)
	etcdutils.PublishControllervalues(t, Controllerhandler)
	fmt.Println("starting registry test")
	mockserviceutils.RunMockDatabase(t, testSessionUid)
	runDeisControllerTest(t, testSessionUid)
	deisControllerServiceTest(t, testSessionUid)
	dockercliutils.ClearTestSession(t, testSessionUid)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"github.com/alexandre-normand/glukit/app/apimodel"
	"github.com/alexandre-normand/glukit/app/util"
	"github.com/spf13/cobra"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var logger = log.New(os.Stderr, "glukameleon", log.LstdFlags)

func main() {
	var inputDirectory string
	var outputFormat string
	var recordType string

	var glukameleonCmd = &cobra.Command{
		Use:   "glukameleon",
		Short: "glukameleon allows to convert dexcom G4 data between different formats",
		Long: `A Fast and Functional converter of XML to JSON Dexcom G4 data.
	       Code can be found at http://github.com/alexandre-normand/glukameleon`,
		Run: func(cmd *cobra.Command, args []string) {
			// Do Stuff Here
		},
	}

	var convertCmd = &cobra.Command{
		Use:   "convert",
		Short: "convert takes a directory of files and converts them to the desired format in a unified file",
		Long:  `Only XML to JSON is support at the moment`,
		Run: func(cmd *cobra.Command, args []string) {
			convert(inputDirectory, recordType, outputFormat)
		},
	}

	convertCmd.Flags().StringVarP(&inputDirectory, "inputDirectory", "i", "", "Source directory to read from")
	convertCmd.Flags().StringVarP(&outputFormat, "format", "f", "", "Output format to write to")
	convertCmd.Flags().StringVarP(&recordType, "recordType", "r", "", "Record type to convert (calibration, glucose, injection, carb)")

	glukameleonCmd.AddCommand(convertCmd)
	glukameleonCmd.Execute()
}

func convert(inputDirectory, recordType, format string) {
	logger.Printf("in Convert")
	_, err := ioutil.ReadDir(inputDirectory)
	if err != nil {
		log.Fatalf("Can't read contents of %s: %v", inputDirectory, err)
	}

	var enc *json.Encoder
	switch format {
	case "json":
		enc = json.NewEncoder(os.Stdout)
		break
	}

	convertFiles(inputDirectory, recordType, enc)
}

func convertFiles(inputDirectory string, recordType string, encoder *json.Encoder) {
	logger.Printf("in ConvertFiles")
	files, err := ioutil.ReadDir(inputDirectory)
	if err != nil {
		log.Fatalf("Can't read contents of %s: %v", inputDirectory, err)
	}

	decoders := make([]*xml.Decoder, 0)
	for _, f := range files {
		if !f.IsDir() {
			dec := newInputDecoder(inputDirectory, f.Name(), recordType, encoder)
			if dec != nil {
				decoders = append(decoders, dec)
			}
		}
	}

	if len(decoders) == 0 {
		logger.Printf("Nothing to do.")
		return
	}
	runConvert(recordType, decoders, encoder)
}

func newInputDecoder(directory string, file string, recordType string, enc *json.Encoder) *xml.Decoder {
	switch ext := filepath.Ext(file); {
	case ext == ".xml":
		fileToConvert, err := os.Open(filepath.Join(directory, file))
		if err != nil {
			log.Fatalf("Can't convert file [%s]: %v", filepath.Join(directory, file), err)
		}

		return xml.NewDecoder(fileToConvert)
	default:
		logger.Printf("Skipping unknown filetype: [%s]", ext)
		return nil
	}
}

func runConvert(recordType string, decoders []*xml.Decoder, enc *json.Encoder) {
	calibrations := make([]apimodel.Calibration, 0)
	glucoseReads := make([]apimodel.Glucose, 0)
	for _, dec := range decoders {
		for {
			// Read tokens from the XML document in a stream.
			t, _ := dec.Token()
			if t == nil {
				logger.Printf("finished reading file")
				break
			}

			// Inspect the type of the token just read.
			switch se := t.(type) {
			case xml.StartElement:
				// If we just read a StartElement token
				// ...and its name is "Glucose"
				switch se.Name.Local {
				case "Glucose":
					var read apimodel.Glucose
					// decode a whole chunk of following XML into the
					dec.DecodeElement(&read, &se)

					if recordType == "glucose" {
						glucoseReads = append(glucoseReads, read)
					}
					break
				case "Event":
					var event apimodel.Event
					dec.DecodeElement(&event, &se)
					//internalEventTime := util.GetTimeInSeconds(event.InternalTime)

					// Skip everything that's before the last import's read time

					if event.EventType == "Carbs" {
						var carbQuantityInGrams int
						fmt.Sscanf(event.Description, "Carbs %d grams", &carbQuantityInGrams)

					} else if event.EventType == "Insulin" {
						var insulinUnits float32
						_, err := fmt.Sscanf(event.Description, "Insulin %f units", &insulinUnits)
						if err != nil {
							util.Propagate(err)
						}

					} else if strings.HasPrefix(event.EventType, "Exercise") {
						var duration int
						var intensity string
						fmt.Sscanf(event.Description, "Exercise %s (%d minutes)", &intensity, &duration)
					}

				case "Meter":
					var c apimodel.Calibration
					dec.DecodeElement(&c, &se)

					if recordType == "calibration" {
						calibrations = append(calibrations, c)
					}
					break
				}
			}
		}
	}

	if len(calibrations) > 0 {
		enc.Encode(&calibrations)
	}

	if len(glucoseReads) > 0 {
		enc.Encode(&glucoseReads)
	}
}
<commit_msg>Implement Support for Event Conversion.<commit_after>package main

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"github.com/alexandre-normand/glukit/app/apimodel"
	"github.com/alexandre-normand/glukit/app/util"
	"github.com/spf13/cobra"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var logger = log.New(os.Stderr, "glukameleon", log.LstdFlags)

func main() {
	var inputDirectory string
	var outputFormat string
	var recordType string

	var glukameleonCmd = &cobra.Command{
		Use:   "glukameleon",
		Short: "glukameleon allows to convert dexcom G4 data between different formats",
		Long: `A Fast and Functional converter of XML to JSON Dexcom G4 data.
	       Code can be found at http://github.com/alexandre-normand/glukameleon`,
		Run: func(cmd *cobra.Command, args []string) {
			// Do Stuff Here
		},
	}

	var convertCmd = &cobra.Command{
		Use:   "convert",
		Short: "convert takes a directory of files and converts them to the desired format in a unified file",
		Long:  `Only XML to JSON is support at the moment`,
		Run: func(cmd *cobra.Command, args []string) {
			convert(inputDirectory, recordType, outputFormat)
		},
	}

	convertCmd.Flags().StringVarP(&inputDirectory, "inputDirectory", "i", "", "Source directory to read from")
	convertCmd.Flags().StringVarP(&outputFormat, "format", "f", "", "Output format to write to")
	convertCmd.Flags().StringVarP(&recordType, "recordType", "r", "", "Record type to convert (calibration, glucose, injection, carb)")

	glukameleonCmd.AddCommand(convertCmd)
	glukameleonCmd.Execute()
}

func convert(inputDirectory, recordType, format string) {
	logger.Printf("in Convert")
	_, err := ioutil.ReadDir(inputDirectory)
	if err != nil {
		log.Fatalf("Can't read contents of %s: %v", inputDirectory, err)
	}

	var enc *json.Encoder
	switch format {
	case "json":
		enc = json.NewEncoder(os.Stdout)
		break
	}

	convertFiles(inputDirectory, recordType, enc)
}

func convertFiles(inputDirectory string, recordType string, encoder *json.Encoder) {
	logger.Printf("in ConvertFiles")
	files, err := ioutil.ReadDir(inputDirectory)
	if err != nil {
		log.Fatalf("Can't read contents of %s: %v", inputDirectory, err)
	}

	decoders := make([]*xml.Decoder, 0)
	for _, f := range files {
		if !f.IsDir() {
			dec := newInputDecoder(inputDirectory, f.Name(), recordType, encoder)
			if dec != nil {
				decoders = append(decoders, dec)
			}
		}
	}

	if len(decoders) == 0 {
		logger.Printf("Nothing to do.")
		return
	}
	runConvert(recordType, decoders, encoder)
}

func newInputDecoder(directory string, file string, recordType string, enc *json.Encoder) *xml.Decoder {
	switch ext := filepath.Ext(file); {
	case ext == ".xml":
		fileToConvert, err := os.Open(filepath.Join(directory, file))
		if err != nil {
			log.Fatalf("Can't convert file [%s]: %v", filepath.Join(directory, file), err)
		}

		return xml.NewDecoder(fileToConvert)
	default:
		logger.Printf("Skipping unknown filetype: [%s]", ext)
		return nil
	}
}

func runConvert(recordType string, decoders []*xml.Decoder, enc *json.Encoder) {
	calibrations := make([]apimodel.Calibration, 0)
	glucoseReads := make([]apimodel.Glucose, 0)
	injections := make([]apimodel.Injection, 0)
	meals := make([]apimodel.Meal, 0)
	exercises := make([]apimodel.Exercise, 0)
	for _, dec := range decoders {
		for {
			// Read tokens from the XML document in a stream.
			t, _ := dec.Token()
			if t == nil {
				logger.Printf("finished reading file")
				break
			}

			// Inspect the type of the token just read.
			switch se := t.(type) {
			case xml.StartElement:
				// If we just read a StartElement token
				// ...and its name is "Glucose"
				switch se.Name.Local {
				case "Glucose":
					var read apimodel.Glucose
					// decode a whole chunk of following XML into the
					dec.DecodeElement(&read, &se)
					if recordType == "glucose" {
						glucoseReads = append(glucoseReads, read)
					}

					break
				case "Event":
					var event apimodel.Event
					dec.DecodeElement(&event, &se)
					if event.EventType == "Carbs" {
						var carbQuantityInGrams int
						fmt.Sscanf(event.Description, "Carbs %d grams", &carbQuantityInGrams)
						carb := apimodel.Meal{apimodel.EventTimestamp{event.DisplayTime, event.InternalTime, event.EventTime}, float32(carbQuantityInGrams), 0., 0., 0.}

						if recordType == "carb" {
							meals = append(meals, carb)
						}
					} else if event.EventType == "Insulin" {
						var insulinUnits float32
						_, err := fmt.Sscanf(event.Description, "Insulin %f units", &insulinUnits)
						if err != nil {
							util.Propagate(err)
						}

						injection := apimodel.Injection{apimodel.EventTimestamp{event.DisplayTime, event.InternalTime, event.EventTime}, float32(insulinUnits), "", ""}

						if recordType == "injection" {
							injections = append(injections, injection)
						}
					} else if strings.HasPrefix(event.EventType, "Exercise") {
						var duration int
						var intensity string
						fmt.Sscanf(event.Description, "Exercise %s (%d minutes)", &intensity, &duration)

						exercise := apimodel.Exercise{apimodel.EventTimestamp{event.DisplayTime, event.InternalTime, event.EventTime}, duration, intensity, ""}

						if recordType == "exercise" {
							exercises = append(exercises, exercise)
						}
					}
				case "Meter":
					var c apimodel.Calibration
					dec.DecodeElement(&c, &se)

					if recordType == "calibration" {
						calibrations = append(calibrations, c)
					}

					break
				}
			}
		}
	}

	if len(calibrations) > 0 {
		enc.Encode(&calibrations)
	}

	if len(glucoseReads) > 0 {
		enc.Encode(&glucoseReads)
	}

	if len(injections) > 0 {
		enc.Encode(&injections)
	}

	if len(exercises) > 0 {
		enc.Encode(&exercises)
	}

	if len(meals) > 0 {
		enc.Encode(&meals)
	}
}
<|endoftext|>


<commit_before>package upcloud

import (
	"log"
	"strconv"

	"github.com/UpCloudLtd/upcloud-go-api/upcloud"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceUpCloudFirewallRule() *schema.Resource {
	return &schema.Resource{
		Create: resourceUpCloudFirewallRuleCreate,
		Read:   resourceUpCloudFirewallRuleRead,
		Delete: resourceUpCloudFirewallRuleDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		Schema: map[string]*schema.Schema{
			"server_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"direction": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"action": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"position": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"family": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"protocol": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Default:  "tcp",
			},
			"icmp_type": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"source_address_start": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"source_address_end": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"source_port_end": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"source_port_start": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"destination_address_start": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"destination_address_end": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"destination_port_start": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"destination_port_end": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"comment": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
		},
	}
}

func resourceUpCloudFirewallRuleCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*service.Service)

	createFirewallRuleRequest := &request.CreateFirewallRuleRequest{
		ServerUUID: d.Get("server_id").(string),
		FirewallRule: upcloud.FirewallRule{
			Direction: d.Get("direction").(string),
			Action:    d.Get("action").(string),
			Family:    d.Get("family").(string),
		},
	}

	if position, ok := d.GetOk("position"); ok {
		position, err := strconv.Atoi(position.(string))
		if err != nil {
			return err
		}
		createFirewallRuleRequest.Position = position
	}

	if protocol, ok := d.GetOk("protocol"); ok {
		createFirewallRuleRequest.Protocol = protocol.(string)
	}

	if icmpType, ok := d.GetOk("icmp_type"); ok {
		createFirewallRuleRequest.ICMPType = icmpType.(string)
	}

	if destinationAddressStart, ok := d.GetOk("destination_address_start"); ok {
		log.Printf("[DEBUG] Destination address start: %+v", destinationAddressStart)
		createFirewallRuleRequest.DestinationAddressStart = destinationAddressStart.(string)
	}

	if destinationAddressEnd, ok := d.GetOk("destination_address_end"); ok {
		log.Printf("[DEBUG] Destination address end: %+v", destinationAddressEnd)
		createFirewallRuleRequest.DestinationAddressEnd = destinationAddressEnd.(string)
	}

	if destinationPortStart, ok := d.GetOk("destination_port_start"); ok {
		createFirewallRuleRequest.DestinationPortStart = destinationPortStart.(string)
	}

	if destinationPortEnd, ok := d.GetOk("destination_port_end"); ok {
		createFirewallRuleRequest.DestinationPortEnd = destinationPortEnd.(string)
	}

	if sourceAddressStart, ok := d.GetOk("source_address_start"); ok {
		createFirewallRuleRequest.SourceAddressStart = sourceAddressStart.(string)
	}

	if sourceAddressEnd, ok := d.GetOk("source_address_end"); ok {
		createFirewallRuleRequest.SourceAddressEnd = sourceAddressEnd.(string)
	}

	if sourcePortStart, ok := d.GetOk("source_port_start"); ok {
		createFirewallRuleRequest.SourcePortStart = sourcePortStart.(string)
	}

	if sourcePortEnd, ok := d.GetOk("source_port_end"); ok {
		createFirewallRuleRequest.SourcePortEnd = sourcePortEnd.(string)
	}

	if comment, ok := d.GetOk("comment"); ok {
		createFirewallRuleRequest.Comment = comment.(string)
	}

	log.Printf("[DEBUG] Firewall rule: %v", createFirewallRuleRequest)

	firewallRule, err := client.CreateFirewallRule(createFirewallRuleRequest)

	if err != nil {
		return err
	}

	d.SetId(createFirewallRuleRequest.ServerUUID + strconv.Itoa(firewallRule.Position))

	return resourceUpCloudFirewallRuleRead(d, meta)
}

func resourceUpCloudFirewallRuleRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*service.Service)
	position, err := strconv.Atoi(d.Get("position").(string))

	if err != nil {
		return err
	}

	r := &request.GetFirewallRuleDetailsRequest{
		ServerUUID: d.Get("server_id").(string),
		Position:   position,
	}

	firewallRule, err := client.GetFirewallRuleDetails(r)

	if err != nil {
		return err
	}

	d.SetId(d.Get("server_id").(string) + strconv.Itoa(firewallRule.Position))
	d.Set("action", firewallRule.Action)
	d.Set("comment", firewallRule.Comment)
	d.Set("destination_address_end", firewallRule.DestinationAddressEnd)
	d.Set("destination_address_start", firewallRule.DestinationAddressStart)
	d.Set("destination_port_end", firewallRule.DestinationPortEnd)
	d.Set("destination_port_start", firewallRule.DestinationPortStart)
	d.Set("direction", firewallRule.Direction)
	d.Set("family", firewallRule.Family)
	d.Set("icmp_type", firewallRule.ICMPType)
	d.Set("position", firewallRule.Position)
	d.Set("protocol", firewallRule.Protocol)
	d.Set("source_address_end", firewallRule.SourceAddressEnd)
	d.Set("source_address_start", firewallRule.SourceAddressStart)
	d.Set("source_port_end", firewallRule.SourcePortEnd)
	d.Set("source_port_start", firewallRule.SourcePortStart)

	return nil
}

func resourceUpCloudFirewallRuleDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*service.Service)

	position, err := strconv.Atoi(d.Get("position").(string))

	if err != nil {
		return err
	}

	deleteFirewallRuleRequest := &request.DeleteFirewallRuleRequest{
		ServerUUID: d.Get("server_id").(string),
		Position:   position,
	}

	err = client.DeleteFirewallRule(deleteFirewallRuleRequest)

	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Changed position in firewall rule to Required instead of Optional.<commit_after>package upcloud

import (
	"log"
	"strconv"

	"github.com/UpCloudLtd/upcloud-go-api/upcloud"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
	"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceUpCloudFirewallRule() *schema.Resource {
	return &schema.Resource{
		Create: resourceUpCloudFirewallRuleCreate,
		Read:   resourceUpCloudFirewallRuleRead,
		Delete: resourceUpCloudFirewallRuleDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		Schema: map[string]*schema.Schema{
			"server_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"direction": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"action": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"position": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"family": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"protocol": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Default:  "tcp",
			},
			"icmp_type": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"source_address_start": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"source_address_end": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"source_port_end": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"source_port_start": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"destination_address_start": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"destination_address_end": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"destination_port_start": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"destination_port_end": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"comment": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
		},
	}
}

func resourceUpCloudFirewallRuleCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*service.Service)

	createFirewallRuleRequest := &request.CreateFirewallRuleRequest{
		ServerUUID: d.Get("server_id").(string),
		FirewallRule: upcloud.FirewallRule{
			Direction: d.Get("direction").(string),
			Action:    d.Get("action").(string),
			Family:    d.Get("family").(string),
		},
	}

	if position, ok := d.GetOk("position"); ok {
		position, err := strconv.Atoi(position.(string))
		if err != nil {
			return err
		}
		createFirewallRuleRequest.Position = position
	}

	if protocol, ok := d.GetOk("protocol"); ok {
		createFirewallRuleRequest.Protocol = protocol.(string)
	}

	if icmpType, ok := d.GetOk("icmp_type"); ok {
		createFirewallRuleRequest.ICMPType = icmpType.(string)
	}

	if destinationAddressStart, ok := d.GetOk("destination_address_start"); ok {
		log.Printf("[DEBUG] Destination address start: %+v", destinationAddressStart)
		createFirewallRuleRequest.DestinationAddressStart = destinationAddressStart.(string)
	}

	if destinationAddressEnd, ok := d.GetOk("destination_address_end"); ok {
		log.Printf("[DEBUG] Destination address end: %+v", destinationAddressEnd)
		createFirewallRuleRequest.DestinationAddressEnd = destinationAddressEnd.(string)
	}

	if destinationPortStart, ok := d.GetOk("destination_port_start"); ok {
		createFirewallRuleRequest.DestinationPortStart = destinationPortStart.(string)
	}

	if destinationPortEnd, ok := d.GetOk("destination_port_end"); ok {
		createFirewallRuleRequest.DestinationPortEnd = destinationPortEnd.(string)
	}

	if sourceAddressStart, ok := d.GetOk("source_address_start"); ok {
		createFirewallRuleRequest.SourceAddressStart = sourceAddressStart.(string)
	}

	if sourceAddressEnd, ok := d.GetOk("source_address_end"); ok {
		createFirewallRuleRequest.SourceAddressEnd = sourceAddressEnd.(string)
	}

	if sourcePortStart, ok := d.GetOk("source_port_start"); ok {
		createFirewallRuleRequest.SourcePortStart = sourcePortStart.(string)
	}

	if sourcePortEnd, ok := d.GetOk("source_port_end"); ok {
		createFirewallRuleRequest.SourcePortEnd = sourcePortEnd.(string)
	}

	if comment, ok := d.GetOk("comment"); ok {
		createFirewallRuleRequest.Comment = comment.(string)
	}

	log.Printf("[DEBUG] Firewall rule: %v", createFirewallRuleRequest)

	firewallRule, err := client.CreateFirewallRule(createFirewallRuleRequest)

	if err != nil {
		return err
	}

	d.SetId(createFirewallRuleRequest.ServerUUID + strconv.Itoa(firewallRule.Position))

	return resourceUpCloudFirewallRuleRead(d, meta)
}

func resourceUpCloudFirewallRuleRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*service.Service)
	position, err := strconv.Atoi(d.Get("position").(string))

	if err != nil {
		return err
	}

	r := &request.GetFirewallRuleDetailsRequest{
		ServerUUID: d.Get("server_id").(string),
		Position:   position,
	}

	firewallRule, err := client.GetFirewallRuleDetails(r)

	if err != nil {
		return err
	}

	d.SetId(d.Get("server_id").(string) + strconv.Itoa(firewallRule.Position))
	d.Set("action", firewallRule.Action)
	d.Set("comment", firewallRule.Comment)
	d.Set("destination_address_end", firewallRule.DestinationAddressEnd)
	d.Set("destination_address_start", firewallRule.DestinationAddressStart)
	d.Set("destination_port_end", firewallRule.DestinationPortEnd)
	d.Set("destination_port_start", firewallRule.DestinationPortStart)
	d.Set("direction", firewallRule.Direction)
	d.Set("family", firewallRule.Family)
	d.Set("icmp_type", firewallRule.ICMPType)
	d.Set("position", firewallRule.Position)
	d.Set("protocol", firewallRule.Protocol)
	d.Set("source_address_end", firewallRule.SourceAddressEnd)
	d.Set("source_address_start", firewallRule.SourceAddressStart)
	d.Set("source_port_end", firewallRule.SourcePortEnd)
	d.Set("source_port_start", firewallRule.SourcePortStart)

	return nil
}

func resourceUpCloudFirewallRuleDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*service.Service)

	position, err := strconv.Atoi(d.Get("position").(string))

	if err != nil {
		return err
	}

	deleteFirewallRuleRequest := &request.DeleteFirewallRuleRequest{
		ServerUUID: d.Get("server_id").(string),
		Position:   position,
	}

	err = client.DeleteFirewallRule(deleteFirewallRuleRequest)

	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>