<commit_before>package main

//go:generate go run generate.go service/*.json

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"text/template"

	"github.com/awslabs/aws-sdk-go/internal/fixtures/helpers"
	"github.com/awslabs/aws-sdk-go/internal/model/api"
	"github.com/awslabs/aws-sdk-go/internal/util"
)

type TestSuite struct {
	API         *api.API
	PackageName string
	APIVersion  string `json:"api_version"`
	Cases       []*TestCase
}

type TestCase struct {
	API         *api.API
	Description string
	Operation   string
	Input       interface{}
	Assertions  []*TestAssertion
}

type TestAssertion struct {
	Case      *TestCase
	Assertion string
	Context   string
	Path      string
	Expected  interface{}
}

var tplTestSuite = template.Must(template.New("testsuite").Parse(`
// +build integration

package {{ .PackageName }}_test

import (
	"testing"

	"github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/internal/util/utilassert"
	"github.com/awslabs/aws-sdk-go/service/{{ .PackageName }}"
	"github.com/stretchr/testify/assert"
)

var (
	_ = assert.Equal
	_ = utilassert.Match
)

{{ range $_, $t := .Cases }}{{ $t.GoCode }}{{ end }}
`))

var tplTestCase = template.Must(template.New("testcase").Parse(`
func Test{{ .TestName }}(t *testing.T) {
	client := {{ .API.PackageName }}.New(nil)
	resp, e := client.{{ .API.ExportableName .Operation }}({{ .InputCode }})
	err := aws.Error(e)
	_, _, _ = resp, e, err // avoid unused warnings

	{{ range $_, $a := .Assertions }}{{ $a.GoCode }}{{ end }}
}
`))

func (t *TestSuite) setup() {
	_, d, _, _ := runtime.Caller(1)
	file := filepath.Join(path.Dir(d), "..", "..", "..", "apis",
		t.PackageName+"-"+t.APIVersion+".normal.json")

	t.API = &api.API{}
	t.API.Attach(file)

	for _, c := range t.Cases {
		c.API = t.API
		for _, a := range c.Assertions {
			a.Case = c
		}
	}
}

func (t *TestSuite) write() {
	_, d, _, _ := runtime.Caller(1)
	file := filepath.Join(path.Dir(d), "..", "..", "..", "service",
		t.PackageName, "integration_test.go")

	var buf bytes.Buffer
	if err := tplTestSuite.Execute(&buf, t); err != nil {
		panic(err)
	}

	b := []byte(util.GoFmt(buf.String()))
	fmt.Println(string(b))
	ioutil.WriteFile(file, b, 0644)
}

func (t *TestCase) TestName() string {
	out := ""
	for _, v := range strings.Split(t.Description, " ") {
		out += util.Capitalize(v)
	}
	return out
}

func (t *TestCase) GoCode() string {
	var buf bytes.Buffer
	if err := tplTestCase.Execute(&buf, t); err != nil {
		panic(err)
	}
	return util.GoFmt(buf.String())
}

func (t *TestCase) InputCode() string {
	op := t.API.Operations[t.Operation]
	if op.InputRef.Shape == nil {
		return ""
	}
	return helpers.ParamsStructFromJSON(t.Input, op.InputRef.Shape, true)
}

func (t *TestAssertion) GoCode() string {
	call, actual, expected := "", "", fmt.Sprintf("%#v", t.Expected)

	if expected == "<nil>" {
		expected = "nil"
	}

	switch t.Context {
	case "error":
		actual = "err"
	case "data":
		actual = "resp"
	default:
		panic("unsupported assertion context " + t.Context)
	}

	if t.Path != "" {
		actual += "." + util.Capitalize(t.Path)
	}

	switch t.Assertion {
	case "typeof":
		return "" // do nothing for typeof checks
	case "equal":
		if actual == "err" && expected == "nil" {
			call = "assert.NoError"
		} else {
			call = "assert.Equal"
		}
	case "notequal":
		call = "assert.NotEqual"
	case "contains":
		call = "utilassert.Match"
	default:
		panic("unsupported assertion type " + t.Assertion)
	}

	return fmt.Sprintf("%s(t, %s, %s)\n", call, expected, actual)
}

func GenerateIntegrationSuite(testFile string) {
	pkgName := strings.Replace(filepath.Base(testFile), ".json", "", -1)
	suite := &TestSuite{PackageName: pkgName}

	if file, err := os.Open(testFile); err == nil {
		defer file.Close()
		if err = json.NewDecoder(file).Decode(&suite); err != nil {
			panic(err)
		}

		suite.setup()
		suite.write()
	} else {
		panic(err)
	}
}

func main() {
	files := []string{}
	for _, arg := range os.Args[1:] {
		paths, _ := filepath.Glob(arg)
		files = append(files, paths...)
	}

	for _, file := range files {
		GenerateIntegrationSuite(file)
	}
}
<commit_msg>Remove debugging println<commit_after>package main

//go:generate go run generate.go service/*.json

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"text/template"

	"github.com/awslabs/aws-sdk-go/internal/fixtures/helpers"
	"github.com/awslabs/aws-sdk-go/internal/model/api"
	"github.com/awslabs/aws-sdk-go/internal/util"
)

type TestSuite struct {
	API         *api.API
	PackageName string
	APIVersion  string `json:"api_version"`
	Cases       []*TestCase
}

type TestCase struct {
	API         *api.API
	Description string
	Operation   string
	Input       interface{}
	Assertions  []*TestAssertion
}

type TestAssertion struct {
	Case      *TestCase
	Assertion string
	Context   string
	Path      string
	Expected  interface{}
}

var tplTestSuite = template.Must(template.New("testsuite").Parse(`
// +build integration

package {{ .PackageName }}_test

import (
	"testing"

	"github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/internal/util/utilassert"
	"github.com/awslabs/aws-sdk-go/service/{{ .PackageName }}"
	"github.com/stretchr/testify/assert"
)

var (
	_ = assert.Equal
	_ = utilassert.Match
)

{{ range $_, $t := .Cases }}{{ $t.GoCode }}{{ end }}
`))

var tplTestCase = template.Must(template.New("testcase").Parse(`
func Test{{ .TestName }}(t *testing.T) {
	client := {{ .API.PackageName }}.New(nil)
	resp, e := client.{{ .API.ExportableName .Operation }}({{ .InputCode }})
	err := aws.Error(e)
	_, _, _ = resp, e, err // avoid unused warnings

	{{ range $_, $a := .Assertions }}{{ $a.GoCode }}{{ end }}
}
`))

func (t *TestSuite) setup() {
	_, d, _, _ := runtime.Caller(1)
	file := filepath.Join(path.Dir(d), "..", "..", "..", "apis",
		t.PackageName+"-"+t.APIVersion+".normal.json")

	t.API = &api.API{}
	t.API.Attach(file)

	for _, c := range t.Cases {
		c.API = t.API
		for _, a := range c.Assertions {
			a.Case = c
		}
	}
}

func (t *TestSuite) write() {
	_, d, _, _ := runtime.Caller(1)
	file := filepath.Join(path.Dir(d), "..", "..", "..", "service",
		t.PackageName, "integration_test.go")

	var buf bytes.Buffer
	if err := tplTestSuite.Execute(&buf, t); err != nil {
		panic(err)
	}

	b := []byte(util.GoFmt(buf.String()))
	ioutil.WriteFile(file, b, 0644)
}

func (t *TestCase) TestName() string {
	out := ""
	for _, v := range strings.Split(t.Description, " ") {
		out += util.Capitalize(v)
	}
	return out
}

func (t *TestCase) GoCode() string {
	var buf bytes.Buffer
	if err := tplTestCase.Execute(&buf, t); err != nil {
		panic(err)
	}
	return util.GoFmt(buf.String())
}

func (t *TestCase) InputCode() string {
	op := t.API.Operations[t.Operation]
	if op.InputRef.Shape == nil {
		return ""
	}
	return helpers.ParamsStructFromJSON(t.Input, op.InputRef.Shape, true)
}

func (t *TestAssertion) GoCode() string {
	call, actual, expected := "", "", fmt.Sprintf("%#v", t.Expected)

	if expected == "<nil>" {
		expected = "nil"
	}

	switch t.Context {
	case "error":
		actual = "err"
	case "data":
		actual = "resp"
	default:
		panic("unsupported assertion context " + t.Context)
	}

	if t.Path != "" {
		actual += "." + util.Capitalize(t.Path)
	}

	switch t.Assertion {
	case "typeof":
		return "" // do nothing for typeof checks
	case "equal":
		if actual == "err" && expected == "nil" {
			call = "assert.NoError"
		} else {
			call = "assert.Equal"
		}
	case "notequal":
		call = "assert.NotEqual"
	case "contains":
		call = "utilassert.Match"
	default:
		panic("unsupported assertion type " + t.Assertion)
	}

	return fmt.Sprintf("%s(t, %s, %s)\n", call, expected, actual)
}

func GenerateIntegrationSuite(testFile string) {
	pkgName := strings.Replace(filepath.Base(testFile), ".json", "", -1)
	suite := &TestSuite{PackageName: pkgName}

	if file, err := os.Open(testFile); err == nil {
		defer file.Close()
		if err = json.NewDecoder(file).Decode(&suite); err != nil {
			panic(err)
		}

		suite.setup()
		suite.write()
	} else {
		panic(err)
	}
}

func main() {
	files := []string{}
	for _, arg := range os.Args[1:] {
		paths, _ := filepath.Glob(arg)
		files = append(files, paths...)
	}

	for _, file := range files {
		GenerateIntegrationSuite(file)
	}
}
<|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 gcsx_test

import (
	"strings"
	"testing"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/gcs/gcsfake"
	"github.com/jacobsa/timeutil"
	"golang.org/x/net/context"
)

var contentTypeBucketTestCases = []struct {
	name     string
	request  string // ContentType in request
	expected string // Expected final type
}{
	/////////////////
	// No extension
	/////////////////

	0: {
		name:     "foo/bar",
		request:  "",
		expected: "",
	},

	1: {
		name:     "foo/bar",
		request:  "image/jpeg",
		expected: "image/jpeg",
	},

	//////////////////////
	// Unknown extension
	//////////////////////

	2: {
		name:     "foo/bar.asdf",
		request:  "",
		expected: "",
	},

	3: {
		name:     "foo/bar.asdf",
		request:  "image/jpeg",
		expected: "image/jpeg",
	},

	//////////////////////
	// Known extension
	//////////////////////

	4: {
		name:     "foo/bar.jpg",
		request:  "",
		expected: "image/jpeg",
	},

	5: {
		name:     "foo/bar.jpg",
		request:  "text/plain",
		expected: "text/plain",
	},
}

func TestContentTypeBucket_CreateObject(t *testing.T) {
	for i, tc := range contentTypeBucketTestCases {
		// Set up a bucket.
		bucket := gcsfake.NewFakeBucket(timeutil.RealClock(), "")

		// Create the object.
		req := &gcs.CreateObjectRequest{
			Name:        tc.name,
			ContentType: tc.request,
			Contents:    strings.NewReader(""),
		}

		o, err := bucket.CreateObject(context.Background(), req)
		if err != nil {
			t.Fatalf("Test case %d: CreateObject: %v", i, err)
		}

		// Check the content type.
		if got, want := o.ContentType, tc.expected; got != want {
			t.Errorf("Test case %d: o.ContentType is %q, want %q", i, got, want)
		}
	}
}

func TestContentTypeBucket_ComposeObjects(t *testing.T) {
	t.Fatal("TODO")
}
<commit_msg>TestContentTypeBucket_ComposeObjects<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 gcsx_test

import (
	"strings"
	"testing"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/gcs/gcsfake"
	"github.com/jacobsa/timeutil"
	"golang.org/x/net/context"
)

var contentTypeBucketTestCases = []struct {
	name     string
	request  string // ContentType in request
	expected string // Expected final type
}{
	/////////////////
	// No extension
	/////////////////

	0: {
		name:     "foo/bar",
		request:  "",
		expected: "",
	},

	1: {
		name:     "foo/bar",
		request:  "image/jpeg",
		expected: "image/jpeg",
	},

	//////////////////////
	// Unknown extension
	//////////////////////

	2: {
		name:     "foo/bar.asdf",
		request:  "",
		expected: "",
	},

	3: {
		name:     "foo/bar.asdf",
		request:  "image/jpeg",
		expected: "image/jpeg",
	},

	//////////////////////
	// Known extension
	//////////////////////

	4: {
		name:     "foo/bar.jpg",
		request:  "",
		expected: "image/jpeg",
	},

	5: {
		name:     "foo/bar.jpg",
		request:  "text/plain",
		expected: "text/plain",
	},
}

func TestContentTypeBucket_CreateObject(t *testing.T) {
	for i, tc := range contentTypeBucketTestCases {
		// Set up a bucket.
		bucket := gcsfake.NewFakeBucket(timeutil.RealClock(), "")

		// Create the object.
		req := &gcs.CreateObjectRequest{
			Name:        tc.name,
			ContentType: tc.request,
			Contents:    strings.NewReader(""),
		}

		o, err := bucket.CreateObject(context.Background(), req)
		if err != nil {
			t.Fatalf("Test case %d: CreateObject: %v", i, err)
		}

		// Check the content type.
		if got, want := o.ContentType, tc.expected; got != want {
			t.Errorf("Test case %d: o.ContentType is %q, want %q", i, got, want)
		}
	}
}

func TestContentTypeBucket_ComposeObjects(t *testing.T) {
	var err error
	ctx := context.Background()

	for i, tc := range contentTypeBucketTestCases {
		// Set up a bucket.
		bucket := gcsfake.NewFakeBucket(timeutil.RealClock(), "")

		// Create a source object.
		const srcName = "some_src"
		_, err = bucket.CreateObject(ctx, &gcs.CreateObjectRequest{
			Name:     srcName,
			Contents: strings.NewReader(""),
		})

		if err != nil {
			t.Fatalf("Test case %d: CreateObject: %v", err)
		}

		// Compose.
		req := &gcs.ComposeObjectsRequest{
			DstName:     tc.name,
			ContentType: tc.request,
			Sources:     []gcs.ComposeSource{{Name: srcName}},
		}

		o, err := bucket.ComposeObjects(ctx, req)
		if err != nil {
			t.Fatalf("Test case %d: ComposeObject: %v", i, err)
		}

		// Check the content type.
		if got, want := o.ContentType, tc.expected; got != want {
			t.Errorf("Test case %d: o.ContentType is %q, want %q", i, got, want)
		}
	}
}
<|endoftext|>


<commit_before>// +build !ignore_autogenerated

/*
Copyright 2018 The Kubernetes Authors.

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

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

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

// This file was autogenerated by deepcopy-gen. Do not edit it manually!

package ingress

import (
	v1 "k8s.io/api/core/v1"
)

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Backend) DeepCopyInto(out *Backend) {
	*out = *in
	if in.Service != nil {
		in, out := &in.Service, &out.Service
		if *in == nil {
			*out = nil
		} else {
			*out = new(v1.Service)
			(*in).DeepCopyInto(*out)
		}
	}
	out.Port = in.Port
	out.SecureCACert = in.SecureCACert
	if in.Endpoints != nil {
		in, out := &in.Endpoints, &out.Endpoints
		*out = make([]Endpoint, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	in.SessionAffinity.DeepCopyInto(&out.SessionAffinity)
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backend.
func (in *Backend) DeepCopy() *Backend {
	if in == nil {
		return nil
	}
	out := new(Backend)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CookieSessionAffinity) DeepCopyInto(out *CookieSessionAffinity) {
	*out = *in
	if in.Locations != nil {
		in, out := &in.Locations, &out.Locations
		*out = make(map[string][]string, len(*in))
		for key, val := range *in {
			if val == nil {
				(*out)[key] = nil
			} else {
				(*out)[key] = make([]string, len(val))
				copy((*out)[key], val)
			}
		}
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CookieSessionAffinity.
func (in *CookieSessionAffinity) DeepCopy() *CookieSessionAffinity {
	if in == nil {
		return nil
	}
	out := new(CookieSessionAffinity)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Endpoint) DeepCopyInto(out *Endpoint) {
	*out = *in
	if in.Target != nil {
		in, out := &in.Target, &out.Target
		if *in == nil {
			*out = nil
		} else {
			*out = new(v1.ObjectReference)
			**out = **in
		}
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint.
func (in *Endpoint) DeepCopy() *Endpoint {
	if in == nil {
		return nil
	}
	out := new(Endpoint)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SessionAffinityConfig) DeepCopyInto(out *SessionAffinityConfig) {
	*out = *in
	in.CookieSessionAffinity.DeepCopyInto(&out.CookieSessionAffinity)
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SessionAffinityConfig.
func (in *SessionAffinityConfig) DeepCopy() *SessionAffinityConfig {
	if in == nil {
		return nil
	}
	out := new(SessionAffinityConfig)
	in.DeepCopyInto(out)
	return out
}
<commit_msg>Update generated code<commit_after>// +build !ignore_autogenerated

/*
Copyright 2019 The Kubernetes Authors.

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

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

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

// Code generated by deepcopy-gen. DO NOT EDIT.

package ingress

import (
	v1 "k8s.io/api/core/v1"
)

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Backend) DeepCopyInto(out *Backend) {
	*out = *in
	if in.Service != nil {
		in, out := &in.Service, &out.Service
		*out = new(v1.Service)
		(*in).DeepCopyInto(*out)
	}
	out.Port = in.Port
	out.SecureCACert = in.SecureCACert
	if in.Endpoints != nil {
		in, out := &in.Endpoints, &out.Endpoints
		*out = make([]Endpoint, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	in.SessionAffinity.DeepCopyInto(&out.SessionAffinity)
	out.UpstreamHashBy = in.UpstreamHashBy
	out.TrafficShapingPolicy = in.TrafficShapingPolicy
	if in.AlternativeBackends != nil {
		in, out := &in.AlternativeBackends, &out.AlternativeBackends
		*out = make([]string, len(*in))
		copy(*out, *in)
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backend.
func (in *Backend) DeepCopy() *Backend {
	if in == nil {
		return nil
	}
	out := new(Backend)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CookieSessionAffinity) DeepCopyInto(out *CookieSessionAffinity) {
	*out = *in
	if in.Locations != nil {
		in, out := &in.Locations, &out.Locations
		*out = make(map[string][]string, len(*in))
		for key, val := range *in {
			var outVal []string
			if val == nil {
				(*out)[key] = nil
			} else {
				in, out := &val, &outVal
				*out = make([]string, len(*in))
				copy(*out, *in)
			}
			(*out)[key] = outVal
		}
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CookieSessionAffinity.
func (in *CookieSessionAffinity) DeepCopy() *CookieSessionAffinity {
	if in == nil {
		return nil
	}
	out := new(CookieSessionAffinity)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Endpoint) DeepCopyInto(out *Endpoint) {
	*out = *in
	if in.Target != nil {
		in, out := &in.Target, &out.Target
		*out = new(v1.ObjectReference)
		**out = **in
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint.
func (in *Endpoint) DeepCopy() *Endpoint {
	if in == nil {
		return nil
	}
	out := new(Endpoint)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SessionAffinityConfig) DeepCopyInto(out *SessionAffinityConfig) {
	*out = *in
	in.CookieSessionAffinity.DeepCopyInto(&out.CookieSessionAffinity)
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SessionAffinityConfig.
func (in *SessionAffinityConfig) DeepCopy() *SessionAffinityConfig {
	if in == nil {
		return nil
	}
	out := new(SessionAffinityConfig)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TrafficShapingPolicy) DeepCopyInto(out *TrafficShapingPolicy) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficShapingPolicy.
func (in *TrafficShapingPolicy) DeepCopy() *TrafficShapingPolicy {
	if in == nil {
		return nil
	}
	out := new(TrafficShapingPolicy)
	in.DeepCopyInto(out)
	return out
}
<|endoftext|>


<commit_before>package commands

import (
	"errors"
	"io"
	"strings"

	oldcmds "github.com/ipfs/go-ipfs/commands"
	lgc "github.com/ipfs/go-ipfs/commands/legacy"
	dag "github.com/ipfs/go-ipfs/core/commands/dag"
	e "github.com/ipfs/go-ipfs/core/commands/e"
	name "github.com/ipfs/go-ipfs/core/commands/name"
	ocmd "github.com/ipfs/go-ipfs/core/commands/object"
	unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs"

	cmds "gx/ipfs/Qma6uuSyjkecGhMFFLfzyJDPyoDtNJSHJNweDccZhaWkgU/go-ipfs-cmds"
	logging "gx/ipfs/QmcuXC5cxs79ro2cUuHs4HQ2bkDLJUYokwL8aivcX6HW3C/go-log"
	"gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
)

var log = logging.Logger("core/commands")

var ErrNotOnline = errors.New("this command must be run in online mode. Try running 'ipfs daemon' first")

const (
	ConfigOption = "config"
	DebugOption  = "debug"
	LocalOption  = "local"
	ApiOption    = "api"
)

var Root = &cmds.Command{
	Helptext: cmdkit.HelpText{
		Tagline:  "Global p2p merkle-dag filesystem.",
		Synopsis: "ipfs [--config=<config> | -c] [--debug=<debug> | -D] [--help=<help>] [-h=<h>] [--local=<local> | -L] [--api=<api>] <command> ...",
		Subcommands: `
BASIC COMMANDS
  init          Initialize ipfs local configuration
  add <path>    Add a file to IPFS
  cat <ref>     Show IPFS object data
  get <ref>     Download IPFS objects
  ls <ref>      List links from an object
  refs <ref>    List hashes of links from an object

DATA STRUCTURE COMMANDS
  block         Interact with raw blocks in the datastore
  object        Interact with raw dag nodes
  files         Interact with objects as if they were a unix filesystem
  dag           Interact with IPLD documents (experimental)

ADVANCED COMMANDS
  daemon        Start a long-running daemon process
  mount         Mount an IPFS read-only mountpoint
  resolve       Resolve any type of name
  name          Publish and resolve IPNS names
  key           Create and list IPNS name keypairs
  dns           Resolve DNS links
  pin           Pin objects to local storage
  repo          Manipulate the IPFS repository
  stats         Various operational stats
  p2p           Libp2p stream mounting
  filestore     Manage the filestore (experimental)

NETWORK COMMANDS
  id            Show info about IPFS peers
  bootstrap     Add or remove bootstrap peers
  swarm         Manage connections to the p2p network
  dht           Query the DHT for values or peers
  ping          Measure the latency of a connection
  diag          Print diagnostics

TOOL COMMANDS
  config        Manage configuration
  version       Show ipfs version information
  update        Download and apply go-ipfs updates
  commands      List all available commands
  cid           Convert and discover properties of CIDs

Use 'ipfs <command> --help' to learn more about each command.

ipfs uses a repository in the local file system. By default, the repo is
located at ~/.ipfs. To change the repo location, set the $IPFS_PATH
environment variable:

  export IPFS_PATH=/path/to/ipfsrepo

EXIT STATUS

The CLI will exit with one of the following values:

0     Successful execution.
1     Failed executions.
`,
	},
	Options: []cmdkit.Option{
		cmdkit.StringOption(ConfigOption, "c", "Path to the configuration file to use."),
		cmdkit.BoolOption(DebugOption, "D", "Operate in debug mode."),
		cmdkit.BoolOption(cmds.OptLongHelp, "Show the full command help text."),
		cmdkit.BoolOption(cmds.OptShortHelp, "Show a short version of the command help text."),
		cmdkit.BoolOption(LocalOption, "L", "Run the command locally, instead of using the daemon."),
		cmdkit.StringOption(ApiOption, "Use a specific API instance (defaults to /ip4/127.0.0.1/tcp/5001)"),

		// global options, added to every command
		cmds.OptionEncodingType,
		cmds.OptionStreamChannels,
		cmds.OptionTimeout,
	},
}

// commandsDaemonCmd is the "ipfs commands" command for daemon
var CommandsDaemonCmd = CommandsCmd(Root)

var rootSubcommands = map[string]*cmds.Command{
	"add":       AddCmd,
	"bitswap":   BitswapCmd,
	"block":     BlockCmd,
	"cat":       CatCmd,
	"commands":  CommandsDaemonCmd,
	"files":     FilesCmd,
	"filestore": FileStoreCmd,
	"get":       GetCmd,
	"pubsub":    PubsubCmd,
	"repo":      RepoCmd,
	"stats":     StatsCmd,
	"bootstrap": BootstrapCmd,
	"config":    ConfigCmd,
	"dag":       dag.DagCmd,
	"dht":       DhtCmd,
	"diag":      DiagCmd,
	"dns":       DNSCmd,
	"id":        IDCmd,
	"key":       KeyCmd,
	"log":       LogCmd,
	"ls":        lgc.NewCommand(LsCmd),
	"mount":     MountCmd,
	"name":      name.NameCmd,
	"object":    ocmd.ObjectCmd,
	"pin":       PinCmd,
	"ping":      PingCmd,
	"p2p":       P2PCmd,
	"refs":      RefsCmd,
	"resolve":   ResolveCmd,
	"swarm":     SwarmCmd,
	"tar":       TarCmd,
	"file":      lgc.NewCommand(unixfs.UnixFSCmd),
	"update":    lgc.NewCommand(ExternalBinary()),
	"urlstore":  urlStoreCmd,
	"version":   VersionCmd,
	"shutdown":  daemonShutdownCmd,
	"cid":       CidCmd,
}

// RootRO is the readonly version of Root
var RootRO = &cmds.Command{}

var CommandsDaemonROCmd = CommandsCmd(RootRO)

// RefsROCmd is `ipfs refs` command
var RefsROCmd = &cmds.Command{}

var rootROSubcommands = map[string]*cmds.Command{
	"commands": CommandsDaemonROCmd,
	"cat":      CatCmd,
	"block": &cmds.Command{
		Subcommands: map[string]*cmds.Command{
			"stat": blockStatCmd,
			"get":  blockGetCmd,
		},
	},
	"get": GetCmd,
	"dns": DNSCmd,
	"ls":  lgc.NewCommand(LsCmd),
	"name": {
		Subcommands: map[string]*cmds.Command{
			"resolve": name.IpnsCmd,
		},
	},
	"object": {
		Subcommands: map[string]*cmds.Command{
			"data":  ocmd.ObjectDataCmd,
			"links": ocmd.ObjectLinksCmd,
			"get":   ocmd.ObjectGetCmd,
			"stat":  ocmd.ObjectStatCmd,
		},
	},
	"dag": {
		Subcommands: map[string]*cmds.Command{
			"get":     dag.DagGetCmd,
			"resolve": dag.DagResolveCmd,
		},
	},
	"resolve": ResolveCmd,
	"version": VersionCmd,
}

func init() {
	Root.ProcessHelp()
	*RootRO = *Root

	// sanitize readonly refs command
	*RefsROCmd = *RefsCmd
	RefsROCmd.Subcommands = map[string]*cmds.Command{}

	// this was in the big map definition above before,
	// but if we leave it there lgc.NewCommand will be executed
	// before the value is updated (:/sanitize readonly refs command/)
	rootROSubcommands["refs"] = RefsROCmd

	Root.Subcommands = rootSubcommands

	RootRO.Subcommands = rootROSubcommands
}

type MessageOutput struct {
	Message string
}

func MessageTextMarshaler(res oldcmds.Response) (io.Reader, error) {
	v, err := unwrapOutput(res.Output())
	if err != nil {
		return nil, err
	}

	out, ok := v.(*MessageOutput)
	if !ok {
		return nil, e.TypeErr(out, v)
	}

	return strings.NewReader(out.Message), nil
}
<commit_msg>cmds: remove reduntant func<commit_after>package commands

import (
	"errors"

	lgc "github.com/ipfs/go-ipfs/commands/legacy"
	dag "github.com/ipfs/go-ipfs/core/commands/dag"
	name "github.com/ipfs/go-ipfs/core/commands/name"
	ocmd "github.com/ipfs/go-ipfs/core/commands/object"
	unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs"

	cmds "gx/ipfs/Qma6uuSyjkecGhMFFLfzyJDPyoDtNJSHJNweDccZhaWkgU/go-ipfs-cmds"
	logging "gx/ipfs/QmcuXC5cxs79ro2cUuHs4HQ2bkDLJUYokwL8aivcX6HW3C/go-log"
	"gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
)

var log = logging.Logger("core/commands")

var ErrNotOnline = errors.New("this command must be run in online mode. Try running 'ipfs daemon' first")

const (
	ConfigOption = "config"
	DebugOption  = "debug"
	LocalOption  = "local"
	ApiOption    = "api"
)

var Root = &cmds.Command{
	Helptext: cmdkit.HelpText{
		Tagline:  "Global p2p merkle-dag filesystem.",
		Synopsis: "ipfs [--config=<config> | -c] [--debug=<debug> | -D] [--help=<help>] [-h=<h>] [--local=<local> | -L] [--api=<api>] <command> ...",
		Subcommands: `
BASIC COMMANDS
  init          Initialize ipfs local configuration
  add <path>    Add a file to IPFS
  cat <ref>     Show IPFS object data
  get <ref>     Download IPFS objects
  ls <ref>      List links from an object
  refs <ref>    List hashes of links from an object

DATA STRUCTURE COMMANDS
  block         Interact with raw blocks in the datastore
  object        Interact with raw dag nodes
  files         Interact with objects as if they were a unix filesystem
  dag           Interact with IPLD documents (experimental)

ADVANCED COMMANDS
  daemon        Start a long-running daemon process
  mount         Mount an IPFS read-only mountpoint
  resolve       Resolve any type of name
  name          Publish and resolve IPNS names
  key           Create and list IPNS name keypairs
  dns           Resolve DNS links
  pin           Pin objects to local storage
  repo          Manipulate the IPFS repository
  stats         Various operational stats
  p2p           Libp2p stream mounting
  filestore     Manage the filestore (experimental)

NETWORK COMMANDS
  id            Show info about IPFS peers
  bootstrap     Add or remove bootstrap peers
  swarm         Manage connections to the p2p network
  dht           Query the DHT for values or peers
  ping          Measure the latency of a connection
  diag          Print diagnostics

TOOL COMMANDS
  config        Manage configuration
  version       Show ipfs version information
  update        Download and apply go-ipfs updates
  commands      List all available commands
  cid           Convert and discover properties of CIDs

Use 'ipfs <command> --help' to learn more about each command.

ipfs uses a repository in the local file system. By default, the repo is
located at ~/.ipfs. To change the repo location, set the $IPFS_PATH
environment variable:

  export IPFS_PATH=/path/to/ipfsrepo

EXIT STATUS

The CLI will exit with one of the following values:

0     Successful execution.
1     Failed executions.
`,
	},
	Options: []cmdkit.Option{
		cmdkit.StringOption(ConfigOption, "c", "Path to the configuration file to use."),
		cmdkit.BoolOption(DebugOption, "D", "Operate in debug mode."),
		cmdkit.BoolOption(cmds.OptLongHelp, "Show the full command help text."),
		cmdkit.BoolOption(cmds.OptShortHelp, "Show a short version of the command help text."),
		cmdkit.BoolOption(LocalOption, "L", "Run the command locally, instead of using the daemon."),
		cmdkit.StringOption(ApiOption, "Use a specific API instance (defaults to /ip4/127.0.0.1/tcp/5001)"),

		// global options, added to every command
		cmds.OptionEncodingType,
		cmds.OptionStreamChannels,
		cmds.OptionTimeout,
	},
}

// commandsDaemonCmd is the "ipfs commands" command for daemon
var CommandsDaemonCmd = CommandsCmd(Root)

var rootSubcommands = map[string]*cmds.Command{
	"add":       AddCmd,
	"bitswap":   BitswapCmd,
	"block":     BlockCmd,
	"cat":       CatCmd,
	"commands":  CommandsDaemonCmd,
	"files":     FilesCmd,
	"filestore": FileStoreCmd,
	"get":       GetCmd,
	"pubsub":    PubsubCmd,
	"repo":      RepoCmd,
	"stats":     StatsCmd,
	"bootstrap": BootstrapCmd,
	"config":    ConfigCmd,
	"dag":       dag.DagCmd,
	"dht":       DhtCmd,
	"diag":      DiagCmd,
	"dns":       DNSCmd,
	"id":        IDCmd,
	"key":       KeyCmd,
	"log":       LogCmd,
	"ls":        lgc.NewCommand(LsCmd),
	"mount":     MountCmd,
	"name":      name.NameCmd,
	"object":    ocmd.ObjectCmd,
	"pin":       PinCmd,
	"ping":      PingCmd,
	"p2p":       P2PCmd,
	"refs":      RefsCmd,
	"resolve":   ResolveCmd,
	"swarm":     SwarmCmd,
	"tar":       TarCmd,
	"file":      lgc.NewCommand(unixfs.UnixFSCmd),
	"update":    lgc.NewCommand(ExternalBinary()),
	"urlstore":  urlStoreCmd,
	"version":   VersionCmd,
	"shutdown":  daemonShutdownCmd,
	"cid":       CidCmd,
}

// RootRO is the readonly version of Root
var RootRO = &cmds.Command{}

var CommandsDaemonROCmd = CommandsCmd(RootRO)

// RefsROCmd is `ipfs refs` command
var RefsROCmd = &cmds.Command{}

var rootROSubcommands = map[string]*cmds.Command{
	"commands": CommandsDaemonROCmd,
	"cat":      CatCmd,
	"block": &cmds.Command{
		Subcommands: map[string]*cmds.Command{
			"stat": blockStatCmd,
			"get":  blockGetCmd,
		},
	},
	"get": GetCmd,
	"dns": DNSCmd,
	"ls":  lgc.NewCommand(LsCmd),
	"name": {
		Subcommands: map[string]*cmds.Command{
			"resolve": name.IpnsCmd,
		},
	},
	"object": {
		Subcommands: map[string]*cmds.Command{
			"data":  ocmd.ObjectDataCmd,
			"links": ocmd.ObjectLinksCmd,
			"get":   ocmd.ObjectGetCmd,
			"stat":  ocmd.ObjectStatCmd,
		},
	},
	"dag": {
		Subcommands: map[string]*cmds.Command{
			"get":     dag.DagGetCmd,
			"resolve": dag.DagResolveCmd,
		},
	},
	"resolve": ResolveCmd,
	"version": VersionCmd,
}

func init() {
	Root.ProcessHelp()
	*RootRO = *Root

	// sanitize readonly refs command
	*RefsROCmd = *RefsCmd
	RefsROCmd.Subcommands = map[string]*cmds.Command{}

	// this was in the big map definition above before,
	// but if we leave it there lgc.NewCommand will be executed
	// before the value is updated (:/sanitize readonly refs command/)
	rootROSubcommands["refs"] = RefsROCmd

	Root.Subcommands = rootSubcommands

	RootRO.Subcommands = rootROSubcommands
}

type MessageOutput struct {
	Message string
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 contiv

import (
	"github.com/contiv/vpp/plugins/contiv/model/cni"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/vpp-agent/clientv1/linux/localclient"
	vpp_intf "github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/model/interfaces"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/l2plugin/model/l2"
	linux_intf "github.com/ligato/vpp-agent/plugins/linuxplugin/model/interfaces"

	"github.com/contiv/vpp/plugins/contiv/containeridx"
	"github.com/contiv/vpp/plugins/kvdbproxy"
	"github.com/gogo/protobuf/proto"
	"github.com/ligato/cn-infra/datasync"
	"golang.org/x/net/context"
	"strconv"
	"strings"
	"sync"
)

type remoteCNIserver struct {
	logging.Logger
	sync.Mutex

	proxy                *kvdbproxy.Plugin
	configuredContainers *containeridx.ConfigIndex

	// bdCreated is true if the bridge domain on the vpp for apackets is configured
	bdCreated bool
	// counter of connected containers. It is used for generating afpacket names
	// and assigned ip addresses.
	counter int
	// created afPacket that are in the bridge domain
	// map is used to support quick removal
	afPackets map[string]interface{}
}

const (
	resultOk             uint32 = 0
	resultErr            uint32 = 1
	vethNameMaxLen              = 15
	bdName                      = "bd1"
	bviName                     = "loop1"
	ipMask                      = "24"
	ipPrefix                    = "10.0.0"
	bviIP                       = ipPrefix + ".254/" + ipMask
	afPacketNamePrefix          = "afpacket"
	podNameExtraArg             = "K8S_POD_NAMESPACE"
	podNamespaceExtraArg        = "K8S_POD_NAME"
)

func newRemoteCNIServer(logger logging.Logger, proxy *kvdbproxy.Plugin, configuredContainers *containeridx.ConfigIndex) *remoteCNIserver {
	return &remoteCNIserver{Logger: logger, afPackets: map[string]interface{}{}, proxy: proxy, configuredContainers: configuredContainers}
}

// Add connects the container to the network.
func (s *remoteCNIserver) Add(ctx context.Context, request *cni.CNIRequest) (*cni.CNIReply, error) {
	s.Info("Add request received ", *request)
	return s.configureContainerConnectivity(request)
}

func (s *remoteCNIserver) Delete(ctx context.Context, request *cni.CNIRequest) (*cni.CNIReply, error) {
	s.Info("Delete request received ", *request)
	return s.unconfigureContainerConnectivity(request)
}

// configureContainerConnectivity creates veth pair where
// one end is ns1 namespace, the other is in default namespace.
// the end in default namespace is connected to VPP using afpacket.
func (s *remoteCNIserver) configureContainerConnectivity(request *cni.CNIRequest) (*cni.CNIReply, error) {
	s.Lock()
	defer s.Unlock()

	var (
		res        = resultOk
		errMsg     = ""
		createdIfs []*cni.CNIReply_Interface
	)

	changes := map[string]proto.Message{}
	s.counter++

	veth1 := s.veth1FromRequest(request)
	veth2 := s.veth2FromRequest(request)
	afpacket := s.afpacketFromRequest(request)

	// create entry in the afpacket map => add afpacket into bridge domain
	s.afPackets[afpacket.Name] = nil

	bd := s.bridgeDomain()

	s.WithFields(logging.Fields{"veth1": veth1, "veth2": veth2, "afpacket": afpacket, "bd": bd}).Info("Configuring")

	txn := localclient.DataChangeRequest("CNI").
		Put().
		LinuxInterface(veth1).
		LinuxInterface(veth2).
		VppInterface(afpacket)

	if !s.bdCreated {
		bvi := s.bviInterface()
		txn.VppInterface(bvi)
		changes[vpp_intf.InterfaceKey(bvi.Name)] = bvi
	}

	err := txn.BD(bd).
		Send().ReceiveReply()

	if err == nil {
		s.bdCreated = true

		changes[linux_intf.InterfaceKey(veth1.Name)] = veth1
		changes[linux_intf.InterfaceKey(veth2.Name)] = veth2
		changes[vpp_intf.InterfaceKey(afpacket.Name)] = afpacket
		changes[l2.BridgeDomainKey(bd.Name)] = bd
		err = s.persistChanges(nil, changes)
		if err != nil {
			errMsg = err.Error()
			res = resultErr
		} else {
			createdIfs = s.createdInterfaces(veth1)

			if s.configuredContainers != nil {
				extraArgs := s.parseExtraArgs(request.ExtraArguments)
				s.Logger.WithFields(logging.Fields{
					"PodName":      extraArgs[podNameExtraArg],
					"PodNamespace": extraArgs[podNamespaceExtraArg],
				}).Info("Adding into configured container index")
				s.configuredContainers.RegisterContainer(request.ContainerId, &containeridx.Config{
					PodName:      extraArgs[podNameExtraArg],
					PodNamespace: extraArgs[podNamespaceExtraArg],
					Veth1:        veth1,
					Veth2:        veth2,
					Afpacket:     afpacket,
				})
			}
		}

	} else {
		res = resultErr
		errMsg = err.Error()
		delete(s.afPackets, afpacket.Name)
	}

	reply := &cni.CNIReply{
		Result:     res,
		Error:      errMsg,
		Interfaces: createdIfs,
		Routes: []*cni.CNIReply_Route{
			{
				Dst: "0.0.0.0/0",
				Gw:  bviIP,
			},
		},
	}
	return reply, err
}

func (s *remoteCNIserver) unconfigureContainerConnectivity(request *cni.CNIRequest) (*cni.CNIReply, error) {
	s.Lock()
	defer s.Unlock()

	var (
		res    = resultOk
		errMsg = ""
	)

	veth1 := s.veth1NameFromRequest(request)
	veth2 := s.veth2NameFromRequest(request)
	afpacket := s.afpacketNameFromRequest(request)
	s.Info("Removing", []string{veth1, veth2, afpacket})
	// remove afpacket from bridge domain
	delete(s.afPackets, afpacket)

	bd := s.bridgeDomain()

	err := localclient.DataChangeRequest("CNI").
		Delete().
		LinuxInterface(veth1).
		LinuxInterface(veth2).
		VppInterface(afpacket).
		Put().BD(bd).
		Send().ReceiveReply()

	if err == nil {
		err = s.persistChanges(
			[]string{linux_intf.InterfaceKey(veth1),
				linux_intf.InterfaceKey(veth2),
				vpp_intf.InterfaceKey(afpacket),
			},
			map[string]proto.Message{l2.BridgeDomainKey(bd.Name): bd},
		)
		if err != nil {
			errMsg = err.Error()
			res = resultErr
		} else {
			if s.configuredContainers != nil {
				s.configuredContainers.UnregisterContainer(request.ContainerId)
			}
		}
	} else {
		res = resultErr
		errMsg = err.Error()
	}

	reply := &cni.CNIReply{
		Result: res,
		Error:  errMsg,
	}
	return reply, err
}

func (s *remoteCNIserver) persistChanges(removedKeys []string, putChanges map[string]proto.Message) error {
	var err error
	// TODO rollback in case of error

	for _, key := range removedKeys {
		s.proxy.AddIgnoreEntry(key, datasync.Delete)
		_, err = s.proxy.Delete(key)
		if err != nil {
			return err
		}
	}

	for k, v := range putChanges {
		s.proxy.AddIgnoreEntry(k, datasync.Put)
		err = s.proxy.Put(k, v)
		if err != nil {
			return err
		}
	}
	return err
}

// createdInterfaces fills the structure containing data of created interfaces
// that is a part of reply to Add request
func (s *remoteCNIserver) createdInterfaces(veth *linux_intf.LinuxInterfaces_Interface) []*cni.CNIReply_Interface {
	return []*cni.CNIReply_Interface{
		{
			Name:    veth.Name,
			Sandbox: veth.Namespace.Name,
			IpAddresses: []*cni.CNIReply_Interface_IP{
				{
					Version: cni.CNIReply_Interface_IP_IPV4,
					Address: veth.IpAddresses[0],
					Gateway: bviIP,
				},
			},
		},
	}
}

func (s *remoteCNIserver) parseExtraArgs(input string) map[string]string {
	res := map[string]string{}

	pairs := strings.Split(input, ";")
	for i := range pairs {
		kv := strings.Split(pairs[i], "=")
		if len(kv) == 2 {
			res[kv[0]] = kv[1]
		}
	}
	return res
}

//
// +-------------------------------------------------+
// |                                                 |
// |                         +----------------+      |
// |                         |     Loop1      |      |
// |      Bridge domain      |     BVI        |      |
// |                         +----------------+      |
// |    +------+       +------+                      |
// |    |  AF1 |       | AFn  |                      |
// |    |      |  ...  |      |                      |
// |    +------+       +------+                      |
// |      ^                                          |
// |      |                                          |
// +------|------------------------------------------+
//        v
// +------------+
// |            |
// | Veth2      |
// |            |
// +------------+
//        ^
//        |
// +------|------------+
// |  NS1 v            |
// |  +------------+   |
// |  |            |   |
// |  | Veth1      |   |
// |  |            |   |
// |  +------------+   |
// |                   |
// +-------------------+

func (s *remoteCNIserver) veth1NameFromRequest(request *cni.CNIRequest) string {
	return request.InterfaceName + request.ContainerId
}

func (s *remoteCNIserver) veth1HostIfNameFromRequest(request *cni.CNIRequest) string {
	return request.InterfaceName
}

func (s *remoteCNIserver) veth2NameFromRequest(request *cni.CNIRequest) string {
	if len(request.ContainerId) > vethNameMaxLen {
		return request.ContainerId[:vethNameMaxLen]
	}
	return request.ContainerId
}

func (s *remoteCNIserver) afpacketNameFromRequest(request *cni.CNIRequest) string {
	return afPacketNamePrefix + s.veth2NameFromRequest(request)
}

func (s *remoteCNIserver) ipAddrForContainer() string {
	return ipPrefix + "." + strconv.Itoa(s.counter) + "/" + ipMask
}

func (s *remoteCNIserver) veth1FromRequest(request *cni.CNIRequest) *linux_intf.LinuxInterfaces_Interface {
	return &linux_intf.LinuxInterfaces_Interface{
		Name:       s.veth1NameFromRequest(request),
		Type:       linux_intf.LinuxInterfaces_VETH,
		Enabled:    true,
		HostIfName: s.veth1HostIfNameFromRequest(request),
		Veth: &linux_intf.LinuxInterfaces_Interface_Veth{
			PeerIfName: s.veth2NameFromRequest(request),
		},
		IpAddresses: []string{s.ipAddrForContainer()},
		Namespace: &linux_intf.LinuxInterfaces_Interface_Namespace{
			Type:     linux_intf.LinuxInterfaces_Interface_Namespace_FILE_REF_NS,
			Filepath: request.NetworkNamespace,
		},
	}
}

func (s *remoteCNIserver) veth2FromRequest(request *cni.CNIRequest) *linux_intf.LinuxInterfaces_Interface {
	return &linux_intf.LinuxInterfaces_Interface{
		Name:       s.veth2NameFromRequest(request),
		Type:       linux_intf.LinuxInterfaces_VETH,
		Enabled:    true,
		HostIfName: s.veth2NameFromRequest(request),
		Veth: &linux_intf.LinuxInterfaces_Interface_Veth{
			PeerIfName: s.veth1NameFromRequest(request),
		},
	}
}

func (s *remoteCNIserver) afpacketFromRequest(request *cni.CNIRequest) *vpp_intf.Interfaces_Interface {
	return &vpp_intf.Interfaces_Interface{
		Name:    s.afpacketNameFromRequest(request),
		Type:    vpp_intf.InterfaceType_AF_PACKET_INTERFACE,
		Enabled: true,
		Afpacket: &vpp_intf.Interfaces_Interface_Afpacket{
			HostIfName: s.veth2NameFromRequest(request),
		},
	}
}

func (s *remoteCNIserver) bridgeDomain() *l2.BridgeDomains_BridgeDomain {
	var ifs = []*l2.BridgeDomains_BridgeDomain_Interfaces{
		{
			Name: bviName,
			BridgedVirtualInterface: true,
		}}

	for af := range s.afPackets {
		ifs = append(ifs, &l2.BridgeDomains_BridgeDomain_Interfaces{
			Name: af,
			BridgedVirtualInterface: false,
		})
	}

	return &l2.BridgeDomains_BridgeDomain{
		Name:                bdName,
		Flood:               true,
		UnknownUnicastFlood: true,
		Forward:             true,
		Learn:               true,
		ArpTermination:      false,
		MacAge:              0, /* means disable aging */
		Interfaces:          ifs,
	}
}

func (s *remoteCNIserver) bviInterface() *vpp_intf.Interfaces_Interface {
	return &vpp_intf.Interfaces_Interface{
		Name:        bviName,
		Enabled:     true,
		IpAddresses: []string{bviIP},
		Type:        vpp_intf.InterfaceType_SOFTWARE_LOOPBACK,
	}
}
<commit_msg>Fix typo<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 contiv

import (
	"github.com/contiv/vpp/plugins/contiv/model/cni"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/vpp-agent/clientv1/linux/localclient"
	vpp_intf "github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/model/interfaces"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/l2plugin/model/l2"
	linux_intf "github.com/ligato/vpp-agent/plugins/linuxplugin/model/interfaces"

	"github.com/contiv/vpp/plugins/contiv/containeridx"
	"github.com/contiv/vpp/plugins/kvdbproxy"
	"github.com/gogo/protobuf/proto"
	"github.com/ligato/cn-infra/datasync"
	"golang.org/x/net/context"
	"strconv"
	"strings"
	"sync"
)

type remoteCNIserver struct {
	logging.Logger
	sync.Mutex

	proxy                *kvdbproxy.Plugin
	configuredContainers *containeridx.ConfigIndex

	// bdCreated is true if the bridge domain on the vpp for apackets is configured
	bdCreated bool
	// counter of connected containers. It is used for generating afpacket names
	// and assigned ip addresses.
	counter int
	// created afPacket that are in the bridge domain
	// map is used to support quick removal
	afPackets map[string]interface{}
}

const (
	resultOk             uint32 = 0
	resultErr            uint32 = 1
	vethNameMaxLen              = 15
	bdName                      = "bd1"
	bviName                     = "loop1"
	ipMask                      = "24"
	ipPrefix                    = "10.0.0"
	bviIP                       = ipPrefix + ".254/" + ipMask
	afPacketNamePrefix          = "afpacket"
	podNameExtraArg             = "K8S_POD_NAME"
	podNamespaceExtraArg        = "K8S_POD_NAMESPACE"
)

func newRemoteCNIServer(logger logging.Logger, proxy *kvdbproxy.Plugin, configuredContainers *containeridx.ConfigIndex) *remoteCNIserver {
	return &remoteCNIserver{Logger: logger, afPackets: map[string]interface{}{}, proxy: proxy, configuredContainers: configuredContainers}
}

// Add connects the container to the network.
func (s *remoteCNIserver) Add(ctx context.Context, request *cni.CNIRequest) (*cni.CNIReply, error) {
	s.Info("Add request received ", *request)
	return s.configureContainerConnectivity(request)
}

func (s *remoteCNIserver) Delete(ctx context.Context, request *cni.CNIRequest) (*cni.CNIReply, error) {
	s.Info("Delete request received ", *request)
	return s.unconfigureContainerConnectivity(request)
}

// configureContainerConnectivity creates veth pair where
// one end is ns1 namespace, the other is in default namespace.
// the end in default namespace is connected to VPP using afpacket.
func (s *remoteCNIserver) configureContainerConnectivity(request *cni.CNIRequest) (*cni.CNIReply, error) {
	s.Lock()
	defer s.Unlock()

	var (
		res        = resultOk
		errMsg     = ""
		createdIfs []*cni.CNIReply_Interface
	)

	changes := map[string]proto.Message{}
	s.counter++

	veth1 := s.veth1FromRequest(request)
	veth2 := s.veth2FromRequest(request)
	afpacket := s.afpacketFromRequest(request)

	// create entry in the afpacket map => add afpacket into bridge domain
	s.afPackets[afpacket.Name] = nil

	bd := s.bridgeDomain()

	s.WithFields(logging.Fields{"veth1": veth1, "veth2": veth2, "afpacket": afpacket, "bd": bd}).Info("Configuring")

	txn := localclient.DataChangeRequest("CNI").
		Put().
		LinuxInterface(veth1).
		LinuxInterface(veth2).
		VppInterface(afpacket)

	if !s.bdCreated {
		bvi := s.bviInterface()
		txn.VppInterface(bvi)
		changes[vpp_intf.InterfaceKey(bvi.Name)] = bvi
	}

	err := txn.BD(bd).
		Send().ReceiveReply()

	if err == nil {
		s.bdCreated = true

		changes[linux_intf.InterfaceKey(veth1.Name)] = veth1
		changes[linux_intf.InterfaceKey(veth2.Name)] = veth2
		changes[vpp_intf.InterfaceKey(afpacket.Name)] = afpacket
		changes[l2.BridgeDomainKey(bd.Name)] = bd
		err = s.persistChanges(nil, changes)
		if err != nil {
			errMsg = err.Error()
			res = resultErr
		} else {
			createdIfs = s.createdInterfaces(veth1)

			if s.configuredContainers != nil {
				extraArgs := s.parseExtraArgs(request.ExtraArguments)
				s.Logger.WithFields(logging.Fields{
					"PodName":      extraArgs[podNameExtraArg],
					"PodNamespace": extraArgs[podNamespaceExtraArg],
				}).Info("Adding into configured container index")
				s.configuredContainers.RegisterContainer(request.ContainerId, &containeridx.Config{
					PodName:      extraArgs[podNameExtraArg],
					PodNamespace: extraArgs[podNamespaceExtraArg],
					Veth1:        veth1,
					Veth2:        veth2,
					Afpacket:     afpacket,
				})
			}
		}

	} else {
		res = resultErr
		errMsg = err.Error()
		delete(s.afPackets, afpacket.Name)
	}

	reply := &cni.CNIReply{
		Result:     res,
		Error:      errMsg,
		Interfaces: createdIfs,
		Routes: []*cni.CNIReply_Route{
			{
				Dst: "0.0.0.0/0",
				Gw:  bviIP,
			},
		},
	}
	return reply, err
}

func (s *remoteCNIserver) unconfigureContainerConnectivity(request *cni.CNIRequest) (*cni.CNIReply, error) {
	s.Lock()
	defer s.Unlock()

	var (
		res    = resultOk
		errMsg = ""
	)

	veth1 := s.veth1NameFromRequest(request)
	veth2 := s.veth2NameFromRequest(request)
	afpacket := s.afpacketNameFromRequest(request)
	s.Info("Removing", []string{veth1, veth2, afpacket})
	// remove afpacket from bridge domain
	delete(s.afPackets, afpacket)

	bd := s.bridgeDomain()

	err := localclient.DataChangeRequest("CNI").
		Delete().
		LinuxInterface(veth1).
		LinuxInterface(veth2).
		VppInterface(afpacket).
		Put().BD(bd).
		Send().ReceiveReply()

	if err == nil {
		err = s.persistChanges(
			[]string{linux_intf.InterfaceKey(veth1),
				linux_intf.InterfaceKey(veth2),
				vpp_intf.InterfaceKey(afpacket),
			},
			map[string]proto.Message{l2.BridgeDomainKey(bd.Name): bd},
		)
		if err != nil {
			errMsg = err.Error()
			res = resultErr
		} else {
			if s.configuredContainers != nil {
				s.configuredContainers.UnregisterContainer(request.ContainerId)
			}
		}
	} else {
		res = resultErr
		errMsg = err.Error()
	}

	reply := &cni.CNIReply{
		Result: res,
		Error:  errMsg,
	}
	return reply, err
}

func (s *remoteCNIserver) persistChanges(removedKeys []string, putChanges map[string]proto.Message) error {
	var err error
	// TODO rollback in case of error

	for _, key := range removedKeys {
		s.proxy.AddIgnoreEntry(key, datasync.Delete)
		_, err = s.proxy.Delete(key)
		if err != nil {
			return err
		}
	}

	for k, v := range putChanges {
		s.proxy.AddIgnoreEntry(k, datasync.Put)
		err = s.proxy.Put(k, v)
		if err != nil {
			return err
		}
	}
	return err
}

// createdInterfaces fills the structure containing data of created interfaces
// that is a part of reply to Add request
func (s *remoteCNIserver) createdInterfaces(veth *linux_intf.LinuxInterfaces_Interface) []*cni.CNIReply_Interface {
	return []*cni.CNIReply_Interface{
		{
			Name:    veth.Name,
			Sandbox: veth.Namespace.Name,
			IpAddresses: []*cni.CNIReply_Interface_IP{
				{
					Version: cni.CNIReply_Interface_IP_IPV4,
					Address: veth.IpAddresses[0],
					Gateway: bviIP,
				},
			},
		},
	}
}

func (s *remoteCNIserver) parseExtraArgs(input string) map[string]string {
	res := map[string]string{}

	pairs := strings.Split(input, ";")
	for i := range pairs {
		kv := strings.Split(pairs[i], "=")
		if len(kv) == 2 {
			res[kv[0]] = kv[1]
		}
	}
	return res
}

//
// +-------------------------------------------------+
// |                                                 |
// |                         +----------------+      |
// |                         |     Loop1      |      |
// |      Bridge domain      |     BVI        |      |
// |                         +----------------+      |
// |    +------+       +------+                      |
// |    |  AF1 |       | AFn  |                      |
// |    |      |  ...  |      |                      |
// |    +------+       +------+                      |
// |      ^                                          |
// |      |                                          |
// +------|------------------------------------------+
//        v
// +------------+
// |            |
// | Veth2      |
// |            |
// +------------+
//        ^
//        |
// +------|------------+
// |  NS1 v            |
// |  +------------+   |
// |  |            |   |
// |  | Veth1      |   |
// |  |            |   |
// |  +------------+   |
// |                   |
// +-------------------+

func (s *remoteCNIserver) veth1NameFromRequest(request *cni.CNIRequest) string {
	return request.InterfaceName + request.ContainerId
}

func (s *remoteCNIserver) veth1HostIfNameFromRequest(request *cni.CNIRequest) string {
	return request.InterfaceName
}

func (s *remoteCNIserver) veth2NameFromRequest(request *cni.CNIRequest) string {
	if len(request.ContainerId) > vethNameMaxLen {
		return request.ContainerId[:vethNameMaxLen]
	}
	return request.ContainerId
}

func (s *remoteCNIserver) afpacketNameFromRequest(request *cni.CNIRequest) string {
	return afPacketNamePrefix + s.veth2NameFromRequest(request)
}

func (s *remoteCNIserver) ipAddrForContainer() string {
	return ipPrefix + "." + strconv.Itoa(s.counter) + "/" + ipMask
}

func (s *remoteCNIserver) veth1FromRequest(request *cni.CNIRequest) *linux_intf.LinuxInterfaces_Interface {
	return &linux_intf.LinuxInterfaces_Interface{
		Name:       s.veth1NameFromRequest(request),
		Type:       linux_intf.LinuxInterfaces_VETH,
		Enabled:    true,
		HostIfName: s.veth1HostIfNameFromRequest(request),
		Veth: &linux_intf.LinuxInterfaces_Interface_Veth{
			PeerIfName: s.veth2NameFromRequest(request),
		},
		IpAddresses: []string{s.ipAddrForContainer()},
		Namespace: &linux_intf.LinuxInterfaces_Interface_Namespace{
			Type:     linux_intf.LinuxInterfaces_Interface_Namespace_FILE_REF_NS,
			Filepath: request.NetworkNamespace,
		},
	}
}

func (s *remoteCNIserver) veth2FromRequest(request *cni.CNIRequest) *linux_intf.LinuxInterfaces_Interface {
	return &linux_intf.LinuxInterfaces_Interface{
		Name:       s.veth2NameFromRequest(request),
		Type:       linux_intf.LinuxInterfaces_VETH,
		Enabled:    true,
		HostIfName: s.veth2NameFromRequest(request),
		Veth: &linux_intf.LinuxInterfaces_Interface_Veth{
			PeerIfName: s.veth1NameFromRequest(request),
		},
	}
}

func (s *remoteCNIserver) afpacketFromRequest(request *cni.CNIRequest) *vpp_intf.Interfaces_Interface {
	return &vpp_intf.Interfaces_Interface{
		Name:    s.afpacketNameFromRequest(request),
		Type:    vpp_intf.InterfaceType_AF_PACKET_INTERFACE,
		Enabled: true,
		Afpacket: &vpp_intf.Interfaces_Interface_Afpacket{
			HostIfName: s.veth2NameFromRequest(request),
		},
	}
}

func (s *remoteCNIserver) bridgeDomain() *l2.BridgeDomains_BridgeDomain {
	var ifs = []*l2.BridgeDomains_BridgeDomain_Interfaces{
		{
			Name: bviName,
			BridgedVirtualInterface: true,
		}}

	for af := range s.afPackets {
		ifs = append(ifs, &l2.BridgeDomains_BridgeDomain_Interfaces{
			Name: af,
			BridgedVirtualInterface: false,
		})
	}

	return &l2.BridgeDomains_BridgeDomain{
		Name:                bdName,
		Flood:               true,
		UnknownUnicastFlood: true,
		Forward:             true,
		Learn:               true,
		ArpTermination:      false,
		MacAge:              0, /* means disable aging */
		Interfaces:          ifs,
	}
}

func (s *remoteCNIserver) bviInterface() *vpp_intf.Interfaces_Interface {
	return &vpp_intf.Interfaces_Interface{
		Name:        bviName,
		Enabled:     true,
		IpAddresses: []string{bviIP},
		Type:        vpp_intf.InterfaceType_SOFTWARE_LOOPBACK,
	}
}
<|endoftext|>


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

// Package cpux provides information about a system's cpus, where X is the
// integer of each CPU on the system, e.g. cpu0, cpu1, etc. On linux systems
// this comes from the sysfs filesystem. Not all paths are available on all
// systems, e.g. /sys/devices/system/cpu/cpuX/cpufreq and its children may not
// exist on some systems. If the system doesn't have a particular path within
// this path, the field's value will be the type's zero value.
//
// This package does not currently have a ticker implementation.
package cpux

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strconv"
	"strings"
)

const (
	SysFSCPUPath = "/sys/devices/system/cpu"
	CPUFreq      = "cpufreq"
	Offline      = "offline"
	Online       = "online"
	Possible     = "possible"
	Present      = "present"
)

type CPUs struct {
	Sockets  int32  `json:"sockets"`
	Possible string `json:"possible"`
	Online   string `json:"online"`
	Offline  string `json:"offline"`
	Present  string `json:"present"`
	CPU      []CPU  `json:"cpu"`
}

type CPU struct {
	PhysicalPackageID int32             `json:"physical_package_id"`
	CoreID            int32             `json:"core_id"`
	MHzMin            float32           `json:"mhz_min"`
	MHzMax            float32           `json:"mhz_max"`
	Cache             map[string]string `json:"cache:`
	// a sorted list of caches so that the cache info can be pulled out in order.
	CacheIDs []string `json:"cache_id"`
}

// GetCPU returns the cpu information for the provided physical_package_id
// (pID) and core_id (coreID). A false will be returned if an entry matching
// the physical_package_id and core_id is not found.
func (c *CPUs) GetCPU(pID, coreID int32) (cpu CPU, found bool) {
	for i := 0; i < len(c.CPU); i++ {
		if c.CPU[i].PhysicalPackageID == pID && c.CPU[i].CoreID == coreID {
			return c.CPU[i], true
		}
	}
	return CPU{}, false
}

// Profiler is used to process the system's cpuX information.
type Profiler struct {
	// this is an exported fied for testing purposes. It should not be set in
	// non-test usage
	NumCPU int
	// this is an exported fied for testing purposes. It should not be set in
	// non-test usage
	SysFSCPUPath string
}

// Returns an initialized Profiler; ready to use.
func NewProfiler() (prof *Profiler, err error) {
	// NumCPU provides the number of logical cpus usable by the current process.
	// Is this sufficient, or will there ever be a delta between that and either
	// what /proc/cpuinfo reports or what is available on /sys/devices/system/cpu/
	return &Profiler{NumCPU: runtime.NumCPU(), SysFSCPUPath: SysFSCPUPath}, nil
}

// Reset resources: this does nothing for this implemenation.
func (prof *Profiler) Reset() error {
	return nil
}

// Get the cpuX info for each cpu. Currently only min and max frequency are
// implemented.
func (prof *Profiler) Get() (*CPUs, error) {
	cpus := &CPUs{CPU: make([]CPU, prof.NumCPU)}
	var err error
	var pids []int32 // the physical ids encountered

	hasFreq := prof.hasCPUFreq()
	for x := 0; x < prof.NumCPU; x++ {
		var cpu CPU
		var found bool

		cpu.PhysicalPackageID, err = prof.physicalPackageID(x)
		if err != nil {
			return nil, err
		}
		// see if this is a new physical id; if so, add it to the inventory
		for _, v := range pids {
			if v == cpu.PhysicalPackageID {
				found = true
				break
			}
		}
		if !found {
			pids = append(pids, cpu.PhysicalPackageID)
		}
		cpu.CoreID, err = prof.coreID(x)
		if err != nil {
			return nil, err
		}
		err := prof.cache(x, &cpu)
		if err != nil {
			return nil, err
		}
		if hasFreq {
			cpu.MHzMin, err = prof.cpuMHzMin(x)
			if err != nil {
				return nil, err
			}
			cpu.MHzMax, err = prof.cpuMHzMax(x)
			if err != nil {
				return nil, err
			}
		}
		cpus.CPU[x] = cpu
	}
	cpus.Sockets = int32(len(pids))
	cpus.Possible, err = prof.Possible()
	if err != nil {
		return nil, err
	}

	cpus.Online, err = prof.Online()
	if err != nil {
		return nil, err
	}

	cpus.Offline, err = prof.Offline()
	if err != nil {
		return nil, err
	}

	cpus.Present, err = prof.Present()
	if err != nil {
		return nil, err
	}

	return cpus, nil
}

// cpuXPath returns the system's cpuX path for a given cpu number.
func (prof *Profiler) cpuXPath(x int) string {
	return fmt.Sprintf("%s/cpu%d", prof.SysFSCPUPath, x)
}

// coreIDPath returns the path of the core_id file for the given cpuX.
func (prof *Profiler) coreIDPath(x int) string {
	return fmt.Sprintf("%s/topology/core_id", prof.cpuXPath(x))
}

// physicalPackageIDPath returns the path of the physical_package_id file for
// the given cpuX.
func (prof *Profiler) physicalPackageIDPath(x int) string {
	return fmt.Sprintf("%s/topology/physical_package_id", prof.cpuXPath(x))
}

// cpuInfoFreqMaxPath returns the path for the cpuinfo_max_freq file of the
// given cpuX.
func (prof *Profiler) cpuInfoFreqMaxPath(x int) string {
	return fmt.Sprintf("%s/cpufreq/cpuinfo_max_freq", prof.cpuXPath(x))
}

// cpuInfoFreqMinPath returns the path for the cpuinfo_min_freq file of the
// given cpuX.
func (prof *Profiler) cpuInfoFreqMinPath(x int) string {
	return fmt.Sprintf("%s/cpufreq/cpuinfo_min_freq", prof.cpuXPath(x))
}

// cachePath returns the path for the cache dir
func (prof *Profiler) cachePath(x int) string {
	return fmt.Sprintf("%s/cache", prof.cpuXPath(x))
}

// hasCPUFreq returns if the system has cpufreq information:
func (prof *Profiler) hasCPUFreq() bool {
	_, err := os.Stat(filepath.Join(prof.SysFSCPUPath, CPUFreq))
	if err == nil {
		return true
	}
	return false
}

// gets the core_id of cpuX
func (prof *Profiler) coreID(x int) (int32, error) {
	v, err := ioutil.ReadFile(prof.coreIDPath(x))
	if err != nil {
		return 0, err
	}
	id, err := strconv.Atoi(string(v[:len(v)-1]))
	if err != nil {
		return 0, fmt.Errorf("cpu%d core_id: conversion error: %s", x, err)
	}
	return int32(id), nil
}

// gets the physical_package_id of cpuX
func (prof *Profiler) physicalPackageID(x int) (int32, error) {
	v, err := ioutil.ReadFile(prof.physicalPackageIDPath(x))
	if err != nil {
		return 0, err
	}
	id, err := strconv.Atoi(string(v[:len(v)-1]))
	if err != nil {
		return 0, fmt.Errorf("cpu%d physical_package_id: conversion error: %s", x, err)
	}
	return int32(id), nil
}

// gets the cpu_mhz_min information
func (prof *Profiler) cpuMHzMin(x int) (float32, error) {
	v, err := ioutil.ReadFile(prof.cpuInfoFreqMinPath(x))
	if err != nil {
		return 0, err
	}
	// insert the . in the appropriate spot
	v = append(v[:len(v)-4], append([]byte{'.'}, v[len(v)-4:len(v)-1]...)...)
	m, err := strconv.ParseFloat(string(v[:len(v)-1]), 32)
	if err != nil {
		return 0, fmt.Errorf("cpu%d MHz min: conversion error: %s", x, err)
	}
	return float32(m), nil
}

// gets the cpu_mhz_max information
func (prof *Profiler) cpuMHzMax(x int) (float32, error) {
	v, err := ioutil.ReadFile(prof.cpuInfoFreqMaxPath(x))
	if err != nil {
		return 0, err
	}
	// insert the . in the appropriate spot
	v = append(v[:len(v)-4], append([]byte{'.'}, v[len(v)-4:len(v)-1]...)...)
	m, err := strconv.ParseFloat(string(v[:len(v)-1]), 32)
	if err != nil {
		return 0, fmt.Errorf("cpu%d MHz max: conversion error: %s", x, err)
	}
	return float32(m), nil
}

// Get the cache info for the given cpuX entry
func (prof *Profiler) cache(x int, cpu *CPU) error {
	cpu.Cache = map[string]string{}
	//go through all the entries in cpuX/cache
	p := prof.cachePath(x)
	dirs, err := ioutil.ReadDir(p)
	if err != nil {
		return err
	}
	var cacheID string
	// all the entries should be dirs with their contents holding the cache info
	for _, d := range dirs {
		if !d.IsDir() {
			continue // this shouldn't happen but if it does we just skip the entry
		}
		// cache level
		l, err := ioutil.ReadFile(filepath.Join(p, d.Name(), "level"))
		if err != nil {
			return err
		}

		t, err := ioutil.ReadFile(filepath.Join(p, d.Name(), "type"))
		if err != nil {
			return err
		}

		// cache type: unified entries aren't decorated, otherwise the first letter is used
		// like what lscpu does.
		if t[0] != 'U' && t[0] != 'u' {
			cacheID = fmt.Sprintf("L%s%s cache", string(l[:len(l)-1]), strings.ToLower(string(t[0])))
		} else {
			cacheID = fmt.Sprintf("L%s cache", string(l[:len(l)-1]))
		}

		// cache size
		s, err := ioutil.ReadFile(filepath.Join(p, d.Name(), "size"))
		if err != nil {
			return err
		}

		// add the info
		cpu.Cache[cacheID] = string(s[:len(s)-1])
		cpu.CacheIDs = append(cpu.CacheIDs, cacheID)
	}
	// sort the cache names
	sort.Strings(cpu.CacheIDs)

	return nil
}

func (prof *Profiler) Possible() (string, error) {
	p, err := ioutil.ReadFile(filepath.Join(prof.SysFSCPUPath, Possible))
	if err != nil {
		return "", err
	}
	return string(p[:len(p)-1]), nil
}

// Present: CPUs that have been identified as being present in the system.
// [cpu_present_mask]
func (prof *Profiler) Present() (string, error) {
	p, err := ioutil.ReadFile(filepath.Join(prof.SysFSCPUPath, Present))
	if err != nil {
		return "", err
	}
	return string(p[:len(p)-1]), nil
}

func (prof *Profiler) Online() (string, error) {
	p, err := ioutil.ReadFile(filepath.Join(prof.SysFSCPUPath, Online))
	if err != nil {
		return "", err
	}
	return string(p[:len(p)-1]), nil
}

// Offline: information about offline cpus. This file may be empty, i.e. only
// contains a '\n', or may not exist; neither of those conditions are an error
// condition.
func (prof *Profiler) Offline() (string, error) {
	p, err := ioutil.ReadFile(filepath.Join(prof.SysFSCPUPath, Offline))
	if err != nil {
		if os.IsNotExist(err) {
			return "", nil
		}
		return "", err
	}
	return string(p[:len(p)-1]), nil
}
<commit_msg>update docs for offline/online/present/possible<commit_after>// Copyright 2016 Joel Scoble and The JoeFriday authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package cpux provides information about a system's cpus, where X is the
// integer of each CPU on the system, e.g. cpu0, cpu1, etc. On linux systems
// this comes from the sysfs filesystem. Not all paths are available on all
// systems, e.g. /sys/devices/system/cpu/cpuX/cpufreq and its children may not
// exist on some systems. If the system doesn't have a particular path within
// this path, the field's value will be the type's zero value.
//
// This package does not currently have a ticker implementation.
package cpux

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strconv"
	"strings"
)

const (
	SysFSCPUPath = "/sys/devices/system/cpu"
	CPUFreq      = "cpufreq"
	Offline      = "offline"
	Online       = "online"
	Possible     = "possible"
	Present      = "present"
)

type CPUs struct {
	Sockets  int32  `json:"sockets"`
	Possible string `json:"possible"`
	Online   string `json:"online"`
	Offline  string `json:"offline"`
	Present  string `json:"present"`
	CPU      []CPU  `json:"cpu"`
}

type CPU struct {
	PhysicalPackageID int32             `json:"physical_package_id"`
	CoreID            int32             `json:"core_id"`
	MHzMin            float32           `json:"mhz_min"`
	MHzMax            float32           `json:"mhz_max"`
	Cache             map[string]string `json:"cache:`
	// a sorted list of caches so that the cache info can be pulled out in order.
	CacheIDs []string `json:"cache_id"`
}

// GetCPU returns the cpu information for the provided physical_package_id
// (pID) and core_id (coreID). A false will be returned if an entry matching
// the physical_package_id and core_id is not found.
func (c *CPUs) GetCPU(pID, coreID int32) (cpu CPU, found bool) {
	for i := 0; i < len(c.CPU); i++ {
		if c.CPU[i].PhysicalPackageID == pID && c.CPU[i].CoreID == coreID {
			return c.CPU[i], true
		}
	}
	return CPU{}, false
}

// Profiler is used to process the system's cpuX information.
type Profiler struct {
	// this is an exported fied for testing purposes. It should not be set in
	// non-test usage
	NumCPU int
	// this is an exported fied for testing purposes. It should not be set in
	// non-test usage
	SysFSCPUPath string
}

// Returns an initialized Profiler; ready to use.
func NewProfiler() (prof *Profiler, err error) {
	// NumCPU provides the number of logical cpus usable by the current process.
	// Is this sufficient, or will there ever be a delta between that and either
	// what /proc/cpuinfo reports or what is available on /sys/devices/system/cpu/
	return &Profiler{NumCPU: runtime.NumCPU(), SysFSCPUPath: SysFSCPUPath}, nil
}

// Reset resources: this does nothing for this implemenation.
func (prof *Profiler) Reset() error {
	return nil
}

// Get the cpuX info for each cpu. Currently only min and max frequency are
// implemented.
func (prof *Profiler) Get() (*CPUs, error) {
	cpus := &CPUs{CPU: make([]CPU, prof.NumCPU)}
	var err error
	var pids []int32 // the physical ids encountered

	hasFreq := prof.hasCPUFreq()
	for x := 0; x < prof.NumCPU; x++ {
		var cpu CPU
		var found bool

		cpu.PhysicalPackageID, err = prof.physicalPackageID(x)
		if err != nil {
			return nil, err
		}
		// see if this is a new physical id; if so, add it to the inventory
		for _, v := range pids {
			if v == cpu.PhysicalPackageID {
				found = true
				break
			}
		}
		if !found {
			pids = append(pids, cpu.PhysicalPackageID)
		}
		cpu.CoreID, err = prof.coreID(x)
		if err != nil {
			return nil, err
		}
		err := prof.cache(x, &cpu)
		if err != nil {
			return nil, err
		}
		if hasFreq {
			cpu.MHzMin, err = prof.cpuMHzMin(x)
			if err != nil {
				return nil, err
			}
			cpu.MHzMax, err = prof.cpuMHzMax(x)
			if err != nil {
				return nil, err
			}
		}
		cpus.CPU[x] = cpu
	}
	cpus.Sockets = int32(len(pids))
	cpus.Possible, err = prof.Possible()
	if err != nil {
		return nil, err
	}

	cpus.Online, err = prof.Online()
	if err != nil {
		return nil, err
	}

	cpus.Offline, err = prof.Offline()
	if err != nil {
		return nil, err
	}

	cpus.Present, err = prof.Present()
	if err != nil {
		return nil, err
	}

	return cpus, nil
}

// cpuXPath returns the system's cpuX path for a given cpu number.
func (prof *Profiler) cpuXPath(x int) string {
	return fmt.Sprintf("%s/cpu%d", prof.SysFSCPUPath, x)
}

// coreIDPath returns the path of the core_id file for the given cpuX.
func (prof *Profiler) coreIDPath(x int) string {
	return fmt.Sprintf("%s/topology/core_id", prof.cpuXPath(x))
}

// physicalPackageIDPath returns the path of the physical_package_id file for
// the given cpuX.
func (prof *Profiler) physicalPackageIDPath(x int) string {
	return fmt.Sprintf("%s/topology/physical_package_id", prof.cpuXPath(x))
}

// cpuInfoFreqMaxPath returns the path for the cpuinfo_max_freq file of the
// given cpuX.
func (prof *Profiler) cpuInfoFreqMaxPath(x int) string {
	return fmt.Sprintf("%s/cpufreq/cpuinfo_max_freq", prof.cpuXPath(x))
}

// cpuInfoFreqMinPath returns the path for the cpuinfo_min_freq file of the
// given cpuX.
func (prof *Profiler) cpuInfoFreqMinPath(x int) string {
	return fmt.Sprintf("%s/cpufreq/cpuinfo_min_freq", prof.cpuXPath(x))
}

// cachePath returns the path for the cache dir
func (prof *Profiler) cachePath(x int) string {
	return fmt.Sprintf("%s/cache", prof.cpuXPath(x))
}

// hasCPUFreq returns if the system has cpufreq information:
func (prof *Profiler) hasCPUFreq() bool {
	_, err := os.Stat(filepath.Join(prof.SysFSCPUPath, CPUFreq))
	if err == nil {
		return true
	}
	return false
}

// gets the core_id of cpuX
func (prof *Profiler) coreID(x int) (int32, error) {
	v, err := ioutil.ReadFile(prof.coreIDPath(x))
	if err != nil {
		return 0, err
	}
	id, err := strconv.Atoi(string(v[:len(v)-1]))
	if err != nil {
		return 0, fmt.Errorf("cpu%d core_id: conversion error: %s", x, err)
	}
	return int32(id), nil
}

// gets the physical_package_id of cpuX
func (prof *Profiler) physicalPackageID(x int) (int32, error) {
	v, err := ioutil.ReadFile(prof.physicalPackageIDPath(x))
	if err != nil {
		return 0, err
	}
	id, err := strconv.Atoi(string(v[:len(v)-1]))
	if err != nil {
		return 0, fmt.Errorf("cpu%d physical_package_id: conversion error: %s", x, err)
	}
	return int32(id), nil
}

// gets the cpu_mhz_min information
func (prof *Profiler) cpuMHzMin(x int) (float32, error) {
	v, err := ioutil.ReadFile(prof.cpuInfoFreqMinPath(x))
	if err != nil {
		return 0, err
	}
	// insert the . in the appropriate spot
	v = append(v[:len(v)-4], append([]byte{'.'}, v[len(v)-4:len(v)-1]...)...)
	m, err := strconv.ParseFloat(string(v[:len(v)-1]), 32)
	if err != nil {
		return 0, fmt.Errorf("cpu%d MHz min: conversion error: %s", x, err)
	}
	return float32(m), nil
}

// gets the cpu_mhz_max information
func (prof *Profiler) cpuMHzMax(x int) (float32, error) {
	v, err := ioutil.ReadFile(prof.cpuInfoFreqMaxPath(x))
	if err != nil {
		return 0, err
	}
	// insert the . in the appropriate spot
	v = append(v[:len(v)-4], append([]byte{'.'}, v[len(v)-4:len(v)-1]...)...)
	m, err := strconv.ParseFloat(string(v[:len(v)-1]), 32)
	if err != nil {
		return 0, fmt.Errorf("cpu%d MHz max: conversion error: %s", x, err)
	}
	return float32(m), nil
}

// Get the cache info for the given cpuX entry
func (prof *Profiler) cache(x int, cpu *CPU) error {
	cpu.Cache = map[string]string{}
	//go through all the entries in cpuX/cache
	p := prof.cachePath(x)
	dirs, err := ioutil.ReadDir(p)
	if err != nil {
		return err
	}
	var cacheID string
	// all the entries should be dirs with their contents holding the cache info
	for _, d := range dirs {
		if !d.IsDir() {
			continue // this shouldn't happen but if it does we just skip the entry
		}
		// cache level
		l, err := ioutil.ReadFile(filepath.Join(p, d.Name(), "level"))
		if err != nil {
			return err
		}

		t, err := ioutil.ReadFile(filepath.Join(p, d.Name(), "type"))
		if err != nil {
			return err
		}

		// cache type: unified entries aren't decorated, otherwise the first letter is used
		// like what lscpu does.
		if t[0] != 'U' && t[0] != 'u' {
			cacheID = fmt.Sprintf("L%s%s cache", string(l[:len(l)-1]), strings.ToLower(string(t[0])))
		} else {
			cacheID = fmt.Sprintf("L%s cache", string(l[:len(l)-1]))
		}

		// cache size
		s, err := ioutil.ReadFile(filepath.Join(p, d.Name(), "size"))
		if err != nil {
			return err
		}

		// add the info
		cpu.Cache[cacheID] = string(s[:len(s)-1])
		cpu.CacheIDs = append(cpu.CacheIDs, cacheID)
	}
	// sort the cache names
	sort.Strings(cpu.CacheIDs)

	return nil
}

// Possible: CPUs that have been allocated resources and can be brought online
// if they are present. [cpu_possible_mask]
// from: Documentation/cputopology.txt
func (prof *Profiler) Possible() (string, error) {
	p, err := ioutil.ReadFile(filepath.Join(prof.SysFSCPUPath, Possible))
	if err != nil {
		return "", err
	}
	return string(p[:len(p)-1]), nil
}

// Present: CPUs that have been identified as being present in the system.
// [cpu_present_mask]
// from: Documentation/cputopology.txt
func (prof *Profiler) Present() (string, error) {
	p, err := ioutil.ReadFile(filepath.Join(prof.SysFSCPUPath, Present))
	if err != nil {
		return "", err
	}
	return string(p[:len(p)-1]), nil
}

// Online: CPUs that are online and being scheduled [cpu_online_mask]
// from: Documentation/cputopology.txt
func (prof *Profiler) Online() (string, error) {
	p, err := ioutil.ReadFile(filepath.Join(prof.SysFSCPUPath, Online))
	if err != nil {
		return "", err
	}
	return string(p[:len(p)-1]), nil
}

// Offline: CPUs that are not online because they have been HOTPLUGGED off
// (see cpu-hotplug.txt) or exceed the limit of CPUs allowed by the kernel
// configuration (kernel_max above). [~cpu_online_mask + cpus >= NR_CPUS].
// from: Documentation/cputopology.txt
//
// This file may not exist or may only contain a new line char, '\n', neither
// of these conditions are error states and will result in an empty string.
func (prof *Profiler) Offline() (string, error) {
	p, err := ioutil.ReadFile(filepath.Join(prof.SysFSCPUPath, Offline))
	if err != nil {
		if os.IsNotExist(err) {
			return "", nil
		}
		return "", err
	}
	return string(p[:len(p)-1]), nil
}
<|endoftext|>


<commit_before>package buffalo

import (
	_ "embed"
)

var (
	//go:embed error.dev.html
	devErrorTmpl string

	//go:embed error.prod.html
	prodErrorTmpl string

	//go:embed notfound.prod.html
	prodNotFoundTmpl string
)
<commit_msg>adding comment for the embed underscore import<commit_after>package buffalo

import (
	_ "embed" // needed to embed the templates.
)

var (
	//go:embed error.dev.html
	devErrorTmpl string

	//go:embed error.prod.html
	prodErrorTmpl string

	//go:embed notfound.prod.html
	prodNotFoundTmpl string
)
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudformation"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSCloudFormation_basic(t *testing.T) {
	var stack cloudformation.Stack

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCloudFormationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCloudFormationConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckCloudFormationStackExists("aws_cloudformation_stack.network", &stack),
				),
			},
		},
	})
}

func TestAccAWSCloudFormation_defaultParams(t *testing.T) {
	var stack cloudformation.Stack

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCloudFormationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCloudFormationConfig_defaultParams,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckCloudFormationStackExists("aws_cloudformation_stack.asg-demo", &stack),
				),
			},
		},
	})
}

func TestAccAWSCloudFormation_allAttributes(t *testing.T) {
	var stack cloudformation.Stack

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCloudFormationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCloudFormationConfig_allAttributes,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckCloudFormationStackExists("aws_cloudformation_stack.full", &stack),
				),
			},
		},
	})
}

func testAccCheckCloudFormationStackExists(n string, stack *cloudformation.Stack) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		conn := testAccProvider.Meta().(*AWSClient).cfconn
		params := &cloudformation.DescribeStacksInput{
			StackName: aws.String(rs.Primary.ID),
		}
		resp, err := conn.DescribeStacks(params)
		if err != nil {
			return err
		}
		if len(resp.Stacks) == 0 {
			return fmt.Errorf("CloudFormation stack not found")
		}

		return nil
	}
}

func testAccCheckAWSCloudFormationDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).cfconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_cloudformation_stack" {
			continue
		}

		params := cloudformation.DescribeStacksInput{
			StackName: aws.String(rs.Primary.ID),
		}

		resp, err := conn.DescribeStacks(&params)

		if err == nil {
			if len(resp.Stacks) != 0 &&
				*resp.Stacks[0].StackId == rs.Primary.ID {
				return fmt.Errorf("CloudFormation stack still exists: %q", rs.Primary.ID)
			}
		}
	}

	return nil
}

var testAccAWSCloudFormationConfig = `
resource "aws_cloudformation_stack" "network" {
  name = "tf-networking-stack"
  template_body = <<STACK
{
  "Resources" : {
    "MyVPC": {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "10.0.0.0/16",
        "Tags" : [
          {"Key": "Name", "Value": "Primary_CF_VPC"}
        ]
      }
    }
  },
  "Outputs" : {
    "DefaultSgId" : {
      "Description": "The ID of default security group",
      "Value" : { "Fn::GetAtt" : [ "MyVPC", "DefaultSecurityGroup" ]}
    },
    "VpcID" : {
      "Description": "The VPC ID",
      "Value" : { "Ref" : "MyVPC" }
    }
  }
}
STACK
}`

var testAccAWSCloudFormationConfig_defaultParams = `
resource "aws_cloudformation_stack" "asg-demo" {
  name = "tf-asg-demo-stack"
  template_body = <<BODY
{
    "Parameters": {
        "TopicName": {
            "Type": "String"
        },
        "VPCCIDR": {
            "Type": "String",
            "Default": "10.10.0.0/16"
        }
    },
    "Resources": {
        "NotificationTopic": {
            "Type": "AWS::SNS::Topic",
            "Properties": {
                "TopicName": {
                    "Ref": "TopicName"
                }
            }
        },
        "MyVPC": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "CidrBlock": {
                    "Ref": "VPCCIDR"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "Primary_CF_VPC"
                    }
                ]
            }
        }
    },
    "Outputs": {
        "VPCCIDR": {
            "Value": {
                "Ref": "VPCCIDR"
            }
        }
    }
}
BODY

  parameters {
    TopicName = "ExampleTopic"
  }
}
`

var testAccAWSCloudFormationConfig_allAttributes = `
resource "aws_cloudformation_stack" "full" {
  name = "tf-full-stack"
  template_body = <<STACK
{
  "Resources" : {
    "MyVPC": {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "10.0.0.0/16",
        "Tags" : [
          {"Key": "Name", "Value": "Primary_CF_VPC"}
        ]
      }
    }
  }
}
STACK

  capabilities = ["CAPABILITY_IAM"]
  notification_arns = ["${aws_sns_topic.cf-updates.arn}"]
  on_failure = "DELETE"
  timeout_in_minutes = 1
}

resource "aws_sns_topic" "cf-updates" {
  name = "tf-cf-notifications"
}
`
<commit_msg>provider/aws: CloudFormation - Add regression test for #4332<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudformation"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSCloudFormation_basic(t *testing.T) {
	var stack cloudformation.Stack

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCloudFormationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCloudFormationConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckCloudFormationStackExists("aws_cloudformation_stack.network", &stack),
				),
			},
		},
	})
}

func TestAccAWSCloudFormation_defaultParams(t *testing.T) {
	var stack cloudformation.Stack

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCloudFormationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCloudFormationConfig_defaultParams,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckCloudFormationStackExists("aws_cloudformation_stack.asg-demo", &stack),
				),
			},
		},
	})
}

func TestAccAWSCloudFormation_allAttributes(t *testing.T) {
	var stack cloudformation.Stack

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCloudFormationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCloudFormationConfig_allAttributes,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckCloudFormationStackExists("aws_cloudformation_stack.full", &stack),
				),
			},
		},
	})
}

// Regression for https://github.com/hashicorp/terraform/issues/4332
func TestAccAWSCloudFormation_withParams(t *testing.T) {
	var stack cloudformation.Stack

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCloudFormationDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCloudFormationConfig_withParams,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with_params", &stack),
				),
			},
			resource.TestStep{
				Config: testAccAWSCloudFormationConfig_withParams_modified,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with_params", &stack),
				),
			},
		},
	})
}

func testAccCheckCloudFormationStackExists(n string, stack *cloudformation.Stack) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		conn := testAccProvider.Meta().(*AWSClient).cfconn
		params := &cloudformation.DescribeStacksInput{
			StackName: aws.String(rs.Primary.ID),
		}
		resp, err := conn.DescribeStacks(params)
		if err != nil {
			return err
		}
		if len(resp.Stacks) == 0 {
			return fmt.Errorf("CloudFormation stack not found")
		}

		return nil
	}
}

func testAccCheckAWSCloudFormationDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).cfconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_cloudformation_stack" {
			continue
		}

		params := cloudformation.DescribeStacksInput{
			StackName: aws.String(rs.Primary.ID),
		}

		resp, err := conn.DescribeStacks(&params)

		if err == nil {
			if len(resp.Stacks) != 0 &&
				*resp.Stacks[0].StackId == rs.Primary.ID {
				return fmt.Errorf("CloudFormation stack still exists: %q", rs.Primary.ID)
			}
		}
	}

	return nil
}

var testAccAWSCloudFormationConfig = `
resource "aws_cloudformation_stack" "network" {
  name = "tf-networking-stack"
  template_body = <<STACK
{
  "Resources" : {
    "MyVPC": {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "10.0.0.0/16",
        "Tags" : [
          {"Key": "Name", "Value": "Primary_CF_VPC"}
        ]
      }
    }
  },
  "Outputs" : {
    "DefaultSgId" : {
      "Description": "The ID of default security group",
      "Value" : { "Fn::GetAtt" : [ "MyVPC", "DefaultSecurityGroup" ]}
    },
    "VpcID" : {
      "Description": "The VPC ID",
      "Value" : { "Ref" : "MyVPC" }
    }
  }
}
STACK
}`

var testAccAWSCloudFormationConfig_defaultParams = `
resource "aws_cloudformation_stack" "asg-demo" {
  name = "tf-asg-demo-stack"
  template_body = <<BODY
{
    "Parameters": {
        "TopicName": {
            "Type": "String"
        },
        "VPCCIDR": {
            "Type": "String",
            "Default": "10.10.0.0/16"
        }
    },
    "Resources": {
        "NotificationTopic": {
            "Type": "AWS::SNS::Topic",
            "Properties": {
                "TopicName": {
                    "Ref": "TopicName"
                }
            }
        },
        "MyVPC": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "CidrBlock": {
                    "Ref": "VPCCIDR"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "Primary_CF_VPC"
                    }
                ]
            }
        }
    },
    "Outputs": {
        "VPCCIDR": {
            "Value": {
                "Ref": "VPCCIDR"
            }
        }
    }
}
BODY

  parameters {
    TopicName = "ExampleTopic"
  }
}
`

var testAccAWSCloudFormationConfig_allAttributes = `
resource "aws_cloudformation_stack" "full" {
  name = "tf-full-stack"
  template_body = <<STACK
{
  "Resources" : {
    "MyVPC": {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "10.0.0.0/16",
        "Tags" : [
          {"Key": "Name", "Value": "Primary_CF_VPC"}
        ]
      }
    }
  }
}
STACK

  capabilities = ["CAPABILITY_IAM"]
  notification_arns = ["${aws_sns_topic.cf-updates.arn}"]
  on_failure = "DELETE"
  timeout_in_minutes = 1
}

resource "aws_sns_topic" "cf-updates" {
  name = "tf-cf-notifications"
}
`

var tpl_testAccAWSCloudFormationConfig_withParams = `
resource "aws_cloudformation_stack" "with_params" {
  name = "tf-stack-with-params"
  parameters {
    VpcCIDR = "%s"
  }
  template_body = <<STACK
{
  "Parameters" : {
    "VpcCIDR" : {
      "Description" : "CIDR to be used for the VPC",
      "Type" : "String"
    }
  },
  "Resources" : {
    "MyVPC": {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : {"Ref": "VpcCIDR"},
        "Tags" : [
          {"Key": "Name", "Value": "Primary_CF_VPC"}
        ]
      }
    }
  }
}
STACK

  on_failure = "DELETE"
  timeout_in_minutes = 1
}
`

var testAccAWSCloudFormationConfig_withParams = fmt.Sprintf(
	tpl_testAccAWSCloudFormationConfig_withParams,
	"10.0.0.0/16")
var testAccAWSCloudFormationConfig_withParams_modified = fmt.Sprintf(
	tpl_testAccAWSCloudFormationConfig_withParams,
	"12.0.0.0/16")
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"

	"github.com/dim13/captcha"
)

var (
	private string
	public  string
	listen  string
)

type Page struct {
	Title  string
	Server string
	Public string
	Ok     string
	Error  string
}

func init() {
	flag.StringVar(&private, "private", "none", "private key")
	flag.StringVar(&public, "public", "none", "public key")
	flag.StringVar(&listen, "listen", ":8000", "listen on")
	flag.Parse()
}

var cc captcha.Captcha

func rootHandler(w http.ResponseWriter, r *http.Request) {
	p := &Page{
		Title:  "reCAPTCHA 1.0",
		Server: cc.Server,
		Public: cc.Public,
	}

	if r.Method == "POST" {
		if ok, err := cc.Verify(r); ok {
			p.Ok = "Valid"
		} else {
			p.Error = err.Error()
		}
	}

	t := template.Must(template.ParseFiles("captcha.tmpl"))
	t.ExecuteTemplate(w, "root", p)
}

func main() {
	if private == "none" || public == "none" {
		flag.PrintDefaults()
		return
	}
	cc = captcha.New(private, public)
	http.HandleFunc("/", rootHandler)
	log.Println("Listen on", listen)
	log.Fatal(http.ListenAndServe(listen, nil))
}
<commit_msg>Simplify example<commit_after>package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"

	"github.com/dim13/captcha"
)

var (
	tmpl    = template.Must(template.ParseFiles("captcha.tmpl"))
	private = flag.String("private", "none", "private key")
	public  = flag.String("public", "none", "public key")
	listen  = flag.String("listen", ":8000", "listen on")
)

type Page struct {
	Title  string
	Server string
	Public string
	Ok     string
	Error  string
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	c := captcha.New(*private, *public)
	p := &Page{
		Title:  "reCAPTCHA 1.0",
		Server: c.Server,
		Public: c.Public,
	}
	if r.Method == "POST" {
		if ok, err := c.Verify(r); ok {
			p.Ok = "Valid"
		} else {
			p.Error = err.Error()
		}
	}
	tmpl.ExecuteTemplate(w, "root", p)
}

func main() {
	flag.Parse()
	if *private == "none" || *public == "none" {
		flag.PrintDefaults()
		return
	}
	http.HandleFunc("/", rootHandler)
	log.Println("Listen on", *listen)
	log.Fatal(http.ListenAndServe(*listen, nil))
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"log"
	"os"
	"time"

	"github.com/goburrow/serial"
)

var address = "/dev/ttyUSB0"

func main() {
	if len(os.Args) > 1 {
		address = os.Args[1]
	}
	port, err := serial.Open(&serial.Config{
		Address: address,
		Timeout: 30 * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer port.Close()

	if _, err = port.Write([]byte("serial")); err != nil {
		log.Fatal(err)
	}
	if _, err = io.Copy(os.Stdout, port); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Add flags to example<commit_after>package main

import (
	"flag"
	"io"
	"log"
	"os"
	"time"

	"github.com/goburrow/serial"
)

var (
	address  string
	baudrate int
	databits int
	stopbits int
	parity   string

	message string
)

func main() {
	flag.StringVar(&address, "a", "/dev/ttyUSB0", "address")
	flag.IntVar(&baudrate, "b", 115200, "baud rate")
	flag.IntVar(&databits, "d", 8, "data bits")
	flag.IntVar(&stopbits, "s", 1, "stop bits")
	flag.StringVar(&parity, "p", "N", "parity (N/E/O)")
	flag.StringVar(&message, "m", "serial", "message")
	flag.Parse()

	config := serial.Config{
		Address:  address,
		BaudRate: baudrate,
		DataBits: databits,
		StopBits: stopbits,
		Parity:   parity,
		Timeout:  30 * time.Second,
	}
	log.Printf("connecting %+v", config)
	port, err := serial.Open(&config)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("connected")
	defer func() {
		err := port.Close()
		if err != nil {
			log.Fatal(err)
		}
		log.Println("closed")
	}()

	if _, err = port.Write([]byte(message)); err != nil {
		log.Fatal(err)
	}
	if _, err = io.Copy(os.Stdout, port); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>