<commit_before>/*
Copyright 2020 The Kubernetes Authors.

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

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

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

package components

import (
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/pkg/apis/kops/util"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/loader"
)

// ClusterAutoscalerOptionsBuilder adds options for cluster autoscaler to the model
type ClusterAutoscalerOptionsBuilder struct {
	*OptionsContext
}

var _ loader.OptionsBuilder = &ClusterAutoscalerOptionsBuilder{}

func (b *ClusterAutoscalerOptionsBuilder) BuildOptions(o interface{}) error {
	clusterSpec := o.(*kops.ClusterSpec)
	cas := clusterSpec.ClusterAutoscaler
	if cas == nil || !fi.BoolValue(cas.Enabled) {
		return nil
	}

	if cas.Image == nil {

		image := "k8s.gcr.io/autoscaling/cluster-autoscaler:latest"
		v, err := util.ParseKubernetesVersion(clusterSpec.KubernetesVersion)
		if err == nil {
			switch v.Minor {
			case 20:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.20.0"
			case 19:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.19.1"
			case 18:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.18.3"
			case 17:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.17.4"
			case 16:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.16.7"
			case 15:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.15.7"
			}
		}
		cas.Image = fi.String(image)

	}

	if cas.Expander == nil {
		cas.Expander = fi.String("random")
	}
	if cas.ScaleDownUtilizationThreshold == nil {
		cas.ScaleDownUtilizationThreshold = fi.String("0.5")
	}
	if cas.SkipNodesWithLocalStorage == nil {
		cas.SkipNodesWithLocalStorage = fi.Bool(true)
	}
	if cas.SkipNodesWithSystemPods == nil {
		cas.SkipNodesWithSystemPods = fi.Bool(true)
	}
	if cas.BalanceSimilarNodeGroups == nil {
		cas.BalanceSimilarNodeGroups = fi.Bool(false)
	}
	if cas.NewPodScaleUpDelay == nil {
		cas.NewPodScaleUpDelay = fi.String("0s")
	}
	if cas.ScaleDownDelayAfterAdd == nil {
		cas.ScaleDownDelayAfterAdd = fi.String("10m0s")
	}

	return nil
}
<commit_msg>Add support for CAS 1.21.0<commit_after>/*
Copyright 2020 The Kubernetes Authors.

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

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

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

package components

import (
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/pkg/apis/kops/util"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/loader"
)

// ClusterAutoscalerOptionsBuilder adds options for cluster autoscaler to the model
type ClusterAutoscalerOptionsBuilder struct {
	*OptionsContext
}

var _ loader.OptionsBuilder = &ClusterAutoscalerOptionsBuilder{}

func (b *ClusterAutoscalerOptionsBuilder) BuildOptions(o interface{}) error {
	clusterSpec := o.(*kops.ClusterSpec)
	cas := clusterSpec.ClusterAutoscaler
	if cas == nil || !fi.BoolValue(cas.Enabled) {
		return nil
	}

	if cas.Image == nil {

		image := "k8s.gcr.io/autoscaling/cluster-autoscaler:latest"
		v, err := util.ParseKubernetesVersion(clusterSpec.KubernetesVersion)
		if err == nil {
			switch v.Minor {
			case 21:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.21.0"
			case 20:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.20.0"
			case 19:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.19.1"
			case 18:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.18.3"
			case 17:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.17.4"
			case 16:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.16.7"
			case 15:
				image = "k8s.gcr.io/autoscaling/cluster-autoscaler:v1.15.7"
			}
		}
		cas.Image = fi.String(image)

	}

	if cas.Expander == nil {
		cas.Expander = fi.String("random")
	}
	if cas.ScaleDownUtilizationThreshold == nil {
		cas.ScaleDownUtilizationThreshold = fi.String("0.5")
	}
	if cas.SkipNodesWithLocalStorage == nil {
		cas.SkipNodesWithLocalStorage = fi.Bool(true)
	}
	if cas.SkipNodesWithSystemPods == nil {
		cas.SkipNodesWithSystemPods = fi.Bool(true)
	}
	if cas.BalanceSimilarNodeGroups == nil {
		cas.BalanceSimilarNodeGroups = fi.Bool(false)
	}
	if cas.NewPodScaleUpDelay == nil {
		cas.NewPodScaleUpDelay = fi.String("0s")
	}
	if cas.ScaleDownDelayAfterAdd == nil {
		cas.ScaleDownDelayAfterAdd = fi.String("10m0s")
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 Google LLC

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 tag

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/GoogleCloudPlatform/skaffold/testutil"
	git "gopkg.in/src-d/go-git.v4"
	"gopkg.in/src-d/go-git.v4/plumbing/object"
)

func TestGitCommit_GenerateFullyQualifiedImageName(t *testing.T) {
	tests := []struct {
		description   string
		expectedName  string
		createGitRepo func(string)
		opts          *TagOptions
		shouldErr     bool
	}{
		{
			description: "success",
			opts: &TagOptions{
				ImageName: "test",
				Digest:    "sha256:12345abcde",
			},
			expectedName: "test:41cf71e",
			createGitRepo: func(dir string) {
				gitInit(t, dir).
					write("source.go", []byte("code")).
					add(t, "source.go").
					commit(t, "initial")
			},
		},
		{
			description: "dirty",
			opts: &TagOptions{
				ImageName: "test",
			},
			expectedName: "test:41cf71e-dirty-17c3e6fb2811b7af",
			createGitRepo: func(dir string) {
				gitInit(t, dir).
					write("source.go", []byte("code")).
					add(t, "source.go").
					commit(t, "initial").
					write("source.go", []byte("updated code"))
			},
		},
		{
			description: "untracked",
			opts: &TagOptions{
				ImageName: "test",
			},
			expectedName: "test:41cf71e-dirty-d7bc32e5f6760a99",
			createGitRepo: func(dir string) {
				gitInit(t, dir).
					write("source.go", []byte("code")).
					add(t, "source.go").
					commit(t, "initial").
					write("new.go", []byte("new code"))
			},
		},
		{
			description:   "failure",
			createGitRepo: func(dir string) {},
			shouldErr:     true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			tmpDir, cleanup := testutil.TempDir(t)
			defer cleanup()

			tt.createGitRepo(tmpDir)

			c := &GitCommit{}
			name, err := c.GenerateFullyQualifiedImageName(tmpDir, tt.opts)

			testutil.CheckErrorAndDeepEqual(t, tt.shouldErr, err, tt.expectedName, name)
		})
	}
}

func TestGenerateFullyQualifiedImageNameFromSubDirectory(t *testing.T) {
	tmpDir, cleanup := testutil.TempDir(t)
	defer cleanup()

	gitInit(t, tmpDir).
		mkdir("sub/sub").
		commit(t, "initial")

	opts := &TagOptions{ImageName: "test"}
	c := &GitCommit{}

	name1, err := c.GenerateFullyQualifiedImageName(tmpDir, opts)
	failNowIfError(t, err)

	subDir := filepath.Join(tmpDir, "sub", "sub")
	name2, err := c.GenerateFullyQualifiedImageName(subDir, opts)
	failNowIfError(t, err)

	if name1 != name2 || name1 != "test:6e0beab" {
		t.Errorf("Invalid names found: %s and %s", name1, name2)
	}
}

// gitRepo deals with test git repositories
type gitRepo struct {
	dir      string
	workTree *git.Worktree
}

func gitInit(t *testing.T, dir string) *gitRepo {
	repo, err := git.PlainInit(dir, false)
	failNowIfError(t, err)

	w, err := repo.Worktree()
	failNowIfError(t, err)

	return &gitRepo{
		dir:      dir,
		workTree: w,
	}
}

func (g *gitRepo) mkdir(folder string) *gitRepo {
	os.MkdirAll(filepath.Join(g.dir, folder), os.ModePerm)
	return g
}

func (g *gitRepo) write(file string, content []byte) *gitRepo {
	ioutil.WriteFile(filepath.Join(g.dir, file), content, 0644)
	return g
}

func (g *gitRepo) add(t *testing.T, file string) *gitRepo {
	_, err := g.workTree.Add(file)
	failNowIfError(t, err)
	return g
}

func (g *gitRepo) commit(t *testing.T, msg string) *gitRepo {
	now, err := time.Parse("Jan 2, 2006 at 3:04pm (MST)", "Feb 3, 2013 at 7:54pm (PST)")
	failNowIfError(t, err)

	_, err = g.workTree.Commit(msg, &git.CommitOptions{
		Author: &object.Signature{
			Name:  "John Doe",
			Email: "john@doe.org",
			When:  now,
		},
	})
	failNowIfError(t, err)

	return g
}

func failNowIfError(t *testing.T, err error) {
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>Handle write errors in test<commit_after>/*
Copyright 2018 Google LLC

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 tag

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/GoogleCloudPlatform/skaffold/testutil"
	git "gopkg.in/src-d/go-git.v4"
	"gopkg.in/src-d/go-git.v4/plumbing/object"
)

func TestGitCommit_GenerateFullyQualifiedImageName(t *testing.T) {
	tests := []struct {
		description   string
		expectedName  string
		createGitRepo func(string)
		opts          *TagOptions
		shouldErr     bool
	}{
		{
			description: "success",
			opts: &TagOptions{
				ImageName: "test",
				Digest:    "sha256:12345abcde",
			},
			expectedName: "test:41cf71e",
			createGitRepo: func(dir string) {
				gitInit(t, dir).
					write(t, "source.go", []byte("code")).
					add(t, "source.go").
					commit(t, "initial")
			},
		},
		{
			description: "dirty",
			opts: &TagOptions{
				ImageName: "test",
			},
			expectedName: "test:41cf71e-dirty-17c3e6fb2811b7af",
			createGitRepo: func(dir string) {
				gitInit(t, dir).
					write(t, "source.go", []byte("code")).
					add(t, "source.go").
					commit(t, "initial").
					write(t, "source.go", []byte("updated code"))
			},
		},
		{
			description: "untracked",
			opts: &TagOptions{
				ImageName: "test",
			},
			expectedName: "test:41cf71e-dirty-d7bc32e5f6760a99",
			createGitRepo: func(dir string) {
				gitInit(t, dir).
					write(t, "source.go", []byte("code")).
					add(t, "source.go").
					commit(t, "initial").
					write(t, "new.go", []byte("new code"))
			},
		},
		{
			description:   "failure",
			createGitRepo: func(dir string) {},
			shouldErr:     true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			tmpDir, cleanup := testutil.TempDir(t)
			defer cleanup()

			tt.createGitRepo(tmpDir)

			c := &GitCommit{}
			name, err := c.GenerateFullyQualifiedImageName(tmpDir, tt.opts)

			testutil.CheckErrorAndDeepEqual(t, tt.shouldErr, err, tt.expectedName, name)
		})
	}
}

func TestGenerateFullyQualifiedImageNameFromSubDirectory(t *testing.T) {
	tmpDir, cleanup := testutil.TempDir(t)
	defer cleanup()

	gitInit(t, tmpDir).
		mkdir("sub/sub").
		commit(t, "initial")

	opts := &TagOptions{ImageName: "test"}
	c := &GitCommit{}

	name1, err := c.GenerateFullyQualifiedImageName(tmpDir, opts)
	failNowIfError(t, err)

	subDir := filepath.Join(tmpDir, "sub", "sub")
	name2, err := c.GenerateFullyQualifiedImageName(subDir, opts)
	failNowIfError(t, err)

	if name1 != name2 || name1 != "test:6e0beab" {
		t.Errorf("Invalid names found: %s and %s", name1, name2)
	}
}

// gitRepo deals with test git repositories
type gitRepo struct {
	dir      string
	workTree *git.Worktree
}

func gitInit(t *testing.T, dir string) *gitRepo {
	repo, err := git.PlainInit(dir, false)
	failNowIfError(t, err)

	w, err := repo.Worktree()
	failNowIfError(t, err)

	return &gitRepo{
		dir:      dir,
		workTree: w,
	}
}

func (g *gitRepo) mkdir(folder string) *gitRepo {
	os.MkdirAll(filepath.Join(g.dir, folder), os.ModePerm)
	return g
}

func (g *gitRepo) write(t *testing.T, file string, content []byte) *gitRepo {
	err := ioutil.WriteFile(filepath.Join(g.dir, file), content, 0644)
	failNowIfError(t, err)
	return g
}

func (g *gitRepo) add(t *testing.T, file string) *gitRepo {
	_, err := g.workTree.Add(file)
	failNowIfError(t, err)
	return g
}

func (g *gitRepo) commit(t *testing.T, msg string) *gitRepo {
	now, err := time.Parse("Jan 2, 2006 at 3:04pm (MST)", "Feb 3, 2013 at 7:54pm (PST)")
	failNowIfError(t, err)

	_, err = g.workTree.Commit(msg, &git.CommitOptions{
		Author: &object.Signature{
			Name:  "John Doe",
			Email: "john@doe.org",
			When:  now,
		},
	})
	failNowIfError(t, err)

	return g
}

func failNowIfError(t *testing.T, err error) {
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package caspercloud

import (
	"crypto/tls"
	"encoding/json"
	"github.com/PuerkitoBio/goquery"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"time"
)

const (
	kParserServer = "http://parser.crawler.bdp.cc/submit"
)

type Mail struct {
	From  string `json:"from"`
	Title string `json:"title"`
}

type CasperOutput struct {
	Downloads []string `json:"downloads"`
	Mails     []Mail   `json:"mails"`
}

func LoadDownloads(fs []string) {
	for _, fn := range fs {
		ParseFile(fn)
	}
}

func ParseFile(fn string) error {
	f, err := os.Open(fn)
	if err != nil {
		log.Println("fail to load file:", err)
		return err
	}
	defer f.Close()

	doc, err := goquery.NewDocumentFromReader(f)
	if err != nil {
		log.Println("fail to get dom:", err)
		return err
	}
	log.Println("file length", len(doc.Text()))
	return nil
}

func newHttpClient(timeOutSeconds int) *http.Client {
	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				timeout := time.Duration(timeOutSeconds) * time.Second
				deadline := time.Now().Add(timeout)
				c, err := net.DialTimeout(netw, addr, timeout)
				if err != nil {
					return nil, err
				}
				c.SetDeadline(deadline)
				return c, nil
			},
			DisableKeepAlives:     true,
			ResponseHeaderTimeout: time.Duration(timeOutSeconds) * time.Second,
			TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
		},
	}
	return client
}

type MailProcessor struct {
	client *http.Client
}

func NewMailProcessor() *MailProcessor {
	c := newHttpClient(20)
	if c == nil {
		return nil
	}

	return &MailProcessor{
		client: c,
	}
}

func (mailProcessor *MailProcessor) deal(info map[string]string, path string) bool {
	log.Println("begin to deal path:", path)
	f, err := os.Open(path)
	if err != nil {
		log.Println("open file failed:", err.Error())
		return false
	}
	defer f.Close()

	fd, err := ioutil.ReadAll(f)
	if err != nil {
		log.Println("read file get error:", err.Error())
		return false
	}

	/*
		msg, err := mail.ReadMessage(f)
		if err != nil {
			log.Println("open file get error:", err.Error())
			return false
		}

		// TODO add header info
		// msg.Header

		body, err := enmime.ParseMIMEBody(msg)
		if err != nil {
			return false
		}
	*/

	info["row_html"] = string(fd)

	value, err := json.Marshal(info)
	if err != nil {
		log.Println("marshal json get err:", err.Error())
		return false
	}
	params := url.Values{}
	params.Set("data", string(value))
	/*
		reqest, err := http.NewRequest("POST", kParserServer, bytes.NewReader([]byte(params.Encode())))
		if err != nil {
			log.Println("new request get error:", err.Error())
			return false
		}

		response, err := mailProcessor.client.Do(reqest)
	*/
	response, err := http.PostForm(kParserServer, params)
	if err != nil || response == nil {
		log.Println("do request get error:", err.Error(), " response:", response)
		return false
	}
	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)

	log.Println("|path|", path, "|post result|", string(body))
	return true

}

func (p *MailProcessor) Process(metaInfo map[string]string, downloads []string) bool {
	for _, fn := range downloads {
		p.deal(metaInfo, fn)
	}
	return true
}
<commit_msg>update ccloud<commit_after>package caspercloud

import (
	"encoding/json"
	"github.com/PuerkitoBio/goquery"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
)

const (
	kParserServer = "http://parser.crawler.bdp.cc/submit"
)

type Mail struct {
	From  string `json:"from"`
	Title string `json:"title"`
}

type CasperOutput struct {
	Downloads []string `json:"downloads"`
	Mails     []Mail   `json:"mails"`
}

func LoadDownloads(fs []string) {
	for _, fn := range fs {
		ParseFile(fn)
	}
}

func ParseFile(fn string) error {
	f, err := os.Open(fn)
	if err != nil {
		log.Println("fail to load file:", err)
		return err
	}
	defer f.Close()

	doc, err := goquery.NewDocumentFromReader(f)
	if err != nil {
		log.Println("fail to get dom:", err)
		return err
	}
	log.Println("file length", len(doc.Text()))
	return nil
}

type MailProcessor struct {
}

func NewMailProcessor() *MailProcessor {
	return &MailProcessor{}
}

func (p *MailProcessor) postData(data string) bool {
	params := url.Values{}
	params.Set("data", data)
	response, err := http.PostForm(kParserServer, params)
	if err != nil || response == nil {
		log.Println("do request get error:", err.Error(), " response:", response)
		return false
	}
	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)

	log.Println("|post result|", string(body))
	return true
}

func (p *MailProcessor) Process(metaInfo map[string]string, downloads []string) bool {
	var mails []string
	for _, fn := range downloads {
		f, err := os.Open(fn)
		if err != nil {
			log.Fatal("open file get error:", err.Error())
		}

		fd, err := ioutil.ReadAll(f)
		if err != nil {
			log.Fatal("read file get error:", err.Error())
		}
		mails = append(mails, string(fd))
		f.Close()
	}
	htmls, err := json.Marshal(mails)
	if err != nil {
		log.Fatal("marshal mails get err:", err.Error())
	}
	metaInfo["row_html"] = string(htmls)
	metaInfo["row_html_len"] = strconv.FormatInt(int64(len(htmls)), 10)

	data, err := json.Marshal(metaInfo)
	if err != nil {
		log.Fatal("marshal metainfo get error:", err.Error())
	}
	p.postData(string(data))
	return true
}
<|endoftext|>


<commit_before>package annotate

import (
	"bytes"
	"io"
	"log"
	"sort"
)

func init() { log.SetFlags(0) }

type Annotation struct {
	Start, End  int
	Left, Right []byte
	WantInner   int
}

type annotations []*Annotation

func (a annotations) Len() int { return len(a) }
func (a annotations) Less(i, j int) bool {
	// Sort by start position, breaking ties by preferring longer
	// matches.
	ai, aj := a[i], a[j]
	if ai.Start == aj.Start {
		if ai.End == aj.End {
			return ai.WantInner < aj.WantInner
		}
		return ai.End > aj.End
	} else {
		return ai.Start < aj.Start
	}
}
func (a annotations) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

func WithHTML(src []byte, anns []*Annotation, encode func(io.Writer, []byte), w io.Writer) error {
	sort.Sort(annotations(anns))
	_, err := annotate(src, 0, len(src), anns, encode, w)
	return err
}

func Annotate(src []byte, left, right int, anns []*Annotation) ([]byte, error) {
	var buf bytes.Buffer
	_, err := annotate(src, left, right, anns, func(w io.Writer, b []byte) { w.Write(b) }, &buf)
	return buf.Bytes(), err
}

func annotate(src []byte, left, right int, anns []*Annotation, encode func(io.Writer, []byte), w io.Writer) (bool, error) {
	runes := []rune(string(src))
	var annotate1 func(left, right int, anns []*Annotation, encode func(io.Writer, []byte), w io.Writer, seen map[*Annotation]struct{}) (bool, error)
	annotate1 = func(left, right int, anns []*Annotation, encode func(io.Writer, []byte), w io.Writer, seen map[*Annotation]struct{}) (bool, error) {
		if encode == nil {
			encode = func(w io.Writer, b []byte) { w.Write(b) }
		}

		rightmost := 0
		for i, ann := range anns {
			if _, exist := seen[ann]; exist {
				continue
			}
			if ann.Start >= right {
				return i != 0, nil
			}
			if ann.End < rightmost {
				continue
			}

			if i == 0 {
				encode(w, []byte(string(runes[left:ann.Start])))
			} else {
				prev := anns[i-1]
				if prev.End >= len(runes) {
					break
				}
				if ann.Start > prev.End {
					encode(w, []byte(string(runes[prev.End:min(ann.Start, len(runes))])))
				}
			}

			w.Write(ann.Left)

			inner, err := annotate1(ann.Start, ann.End, anns[i+1:], encode, w, seen)
			if err != nil {
				return false, err
			}

			if !inner {
				if ann.Start >= len(runes) {
					break
				}
				b := []byte(string(runes[ann.Start:min(ann.End, len(runes))]))
				encode(w, b)
			}

			w.Write(ann.Right)
			seen[ann] = struct{}{}

			if i == len(anns)-1 {
				if ann.End < len(runes) {
					// TODO(sqs): fix this. it chops off a portion of an
					// annotation.
					if right < ann.End {
						right = ann.End
					}
					encode(w, []byte(string(runes[ann.End:min(right, len(runes))])))
				}
			}

			rightmost = ann.End
		}
		return len(anns) > 0, nil
	}

	seen := make(map[*Annotation]struct{})
	return annotate1(left, right, anns, encode, w, seen)
}

func min(a, b int) int {
	if a > b {
		return b
	}
	return a
}
<commit_msg>rm init<commit_after>package annotate

import (
	"bytes"
	"io"
	"sort"
)

type Annotation struct {
	Start, End  int
	Left, Right []byte
	WantInner   int
}

type annotations []*Annotation

func (a annotations) Len() int { return len(a) }
func (a annotations) Less(i, j int) bool {
	// Sort by start position, breaking ties by preferring longer
	// matches.
	ai, aj := a[i], a[j]
	if ai.Start == aj.Start {
		if ai.End == aj.End {
			return ai.WantInner < aj.WantInner
		}
		return ai.End > aj.End
	} else {
		return ai.Start < aj.Start
	}
}
func (a annotations) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

func WithHTML(src []byte, anns []*Annotation, encode func(io.Writer, []byte), w io.Writer) error {
	sort.Sort(annotations(anns))
	_, err := annotate(src, 0, len(src), anns, encode, w)
	return err
}

func Annotate(src []byte, left, right int, anns []*Annotation) ([]byte, error) {
	var buf bytes.Buffer
	_, err := annotate(src, left, right, anns, func(w io.Writer, b []byte) { w.Write(b) }, &buf)
	return buf.Bytes(), err
}

func annotate(src []byte, left, right int, anns []*Annotation, encode func(io.Writer, []byte), w io.Writer) (bool, error) {
	runes := []rune(string(src))
	var annotate1 func(left, right int, anns []*Annotation, encode func(io.Writer, []byte), w io.Writer, seen map[*Annotation]struct{}) (bool, error)
	annotate1 = func(left, right int, anns []*Annotation, encode func(io.Writer, []byte), w io.Writer, seen map[*Annotation]struct{}) (bool, error) {
		if encode == nil {
			encode = func(w io.Writer, b []byte) { w.Write(b) }
		}

		rightmost := 0
		for i, ann := range anns {
			if _, exist := seen[ann]; exist {
				continue
			}
			if ann.Start >= right {
				return i != 0, nil
			}
			if ann.End < rightmost {
				continue
			}

			if i == 0 {
				encode(w, []byte(string(runes[left:ann.Start])))
			} else {
				prev := anns[i-1]
				if prev.End >= len(runes) {
					break
				}
				if ann.Start > prev.End {
					encode(w, []byte(string(runes[prev.End:min(ann.Start, len(runes))])))
				}
			}

			w.Write(ann.Left)

			inner, err := annotate1(ann.Start, ann.End, anns[i+1:], encode, w, seen)
			if err != nil {
				return false, err
			}

			if !inner {
				if ann.Start >= len(runes) {
					break
				}
				b := []byte(string(runes[ann.Start:min(ann.End, len(runes))]))
				encode(w, b)
			}

			w.Write(ann.Right)
			seen[ann] = struct{}{}

			if i == len(anns)-1 {
				if ann.End < len(runes) {
					// TODO(sqs): fix this. it chops off a portion of an
					// annotation.
					if right < ann.End {
						right = ann.End
					}
					encode(w, []byte(string(runes[ann.End:min(right, len(runes))])))
				}
			}

			rightmost = ann.End
		}
		return len(anns) > 0, nil
	}

	seen := make(map[*Annotation]struct{})
	return annotate1(left, right, anns, encode, w, seen)
}

func min(a, b int) int {
	if a > b {
		return b
	}
	return a
}
<|endoftext|>


<commit_before>package brctl

import (
	"bufio"
	"fmt"
	"io"
	"regexp"
	"strings"
)

type Bridge struct {
	Name       string
	ID         string
	STP        bool
	Interfaces []string
}

func parseBrctlShowDeclLine(line string) (*Bridge, error) {
	line = strings.TrimSpace(line)
	parts := regexp.MustCompile("\\s+").Split(line, -1)
	if len(parts) != 4 && len(parts) != 3 {
		return nil, fmt.Errorf("not a valid brctl bridge declaration: '%s'", line)
	}

	b := Bridge{
		Name: parts[0],
		ID:   parts[1],
		STP:  false,
	}
	if parts[2] == "yes" {
		b.STP = true
	}
	if len(parts) == 4 {
		b.Interfaces = []string{parts[3]}
	}
	return &b, nil
}

func parseBrctlShowIntefaceLine(line string) string {
	return strings.TrimSpace(line)
}

func parseBrctlShow(reader io.Reader) ([]Bridge, error) {
	whitespace := regexp.MustCompile("^\\s+.*$")
	s := bufio.NewScanner(reader)

	// Discard header
	if !s.Scan() {
		return nil, s.Err()
	}

	// Parse bridges
	var current *Bridge
	bridges := make([]Bridge, 0)
	for i := 2; s.Scan(); i++ {
		line := s.Text()
		if len(line) == 0 {
			return nil, fmt.Errorf("line %d: unexpected empty line", i)
		}

		if whitespace.MatchString(line) {
			if current == nil {
				return nil, fmt.Errorf("line %d: no bridge declaration before interface spec", i)
			}
			current.Interfaces = append(current.Interfaces, parseBrctlShowIntefaceLine(line))
		} else {
			if current != nil {
				bridges = append(bridges, *current)
			}
			b, err := parseBrctlShowDeclLine(line)
			if err != nil {
				return nil, fmt.Errorf("line %d: %v", i, err)
			}
			current = b
		}
	}

	if current != nil {
		bridges = append(bridges, *current)
	}

	return bridges, s.Err()
}
<commit_msg>Implement brctl.Show function<commit_after>package brctl

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os/exec"
	"regexp"
	"strings"
)

type Bridge struct {
	Name       string
	ID         string
	STP        bool
	Interfaces []string
}

func Show() ([]Bridge, error) {
	out, err := exec.Command("brctl", "show").Output()
	if err != nil {
		return nil, err
	}

	return parseBrctlShow(bytes.NewBuffer(out))
}

func parseBrctlShowDeclLine(line string) (*Bridge, error) {
	line = strings.TrimSpace(line)
	parts := regexp.MustCompile("\\s+").Split(line, -1)
	if len(parts) != 4 && len(parts) != 3 {
		return nil, fmt.Errorf("not a valid brctl bridge declaration: '%s'", line)
	}

	b := Bridge{
		Name: parts[0],
		ID:   parts[1],
		STP:  false,
	}
	if parts[2] == "yes" {
		b.STP = true
	}
	if len(parts) == 4 {
		b.Interfaces = []string{parts[3]}
	}
	return &b, nil
}

func parseBrctlShowIntefaceLine(line string) string {
	return strings.TrimSpace(line)
}

func parseBrctlShow(reader io.Reader) ([]Bridge, error) {
	whitespace := regexp.MustCompile("^\\s+.*$")
	s := bufio.NewScanner(reader)

	// Discard header
	if !s.Scan() {
		return nil, s.Err()
	}

	// Parse bridges
	var current *Bridge
	bridges := make([]Bridge, 0)
	for i := 2; s.Scan(); i++ {
		line := s.Text()
		if len(line) == 0 {
			return nil, fmt.Errorf("line %d: unexpected empty line", i)
		}

		if whitespace.MatchString(line) {
			if current == nil {
				return nil, fmt.Errorf("line %d: no bridge declaration before interface spec", i)
			}
			current.Interfaces = append(current.Interfaces, parseBrctlShowIntefaceLine(line))
		} else {
			if current != nil {
				bridges = append(bridges, *current)
			}
			b, err := parseBrctlShowDeclLine(line)
			if err != nil {
				return nil, fmt.Errorf("line %d: %v", i, err)
			}
			current = b
		}
	}

	if current != nil {
		bridges = append(bridges, *current)
	}

	return bridges, s.Err()
}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type isval []byte

type MarketerStruct struct {
	EId                   string `json:"EId"`
	TaxId                 string `json:"TaxId"`
	BeginDate             string `json:"BeginDate"`
	MarketerTypeFlag      string `json:"MarketerTypeFlag"`
	MarketerType          string `json:"MarketerType"`
	MarketerRole          string `json:"MarketerRole"`
	MarketerStatus        string `json:"MarketerStatus"`
	LegalName             string `json:"LegalName"`
	Gender                string `json:"Gender"`
	DoB                   string `json:"DoB"`
	RegStateName          string `json:"RegStateName"`
	MarketerEffectiveDate string `json:"MarketerEffectiveDate"`
	MarketerEndDate       string `json:"MarketerEndDate"`
	FirstName             string `json:"FirstName"`
	LastName              string `json:"LastName"`
	BusinessAddress       string `json:"BusinessAddress"`
	City                  string `json:"City"`
	State                 string `json:"State"`
	PostalCode            string `json:"PostalCode"`
	PhoneNumber           string `json:"PhoneNumber"`
	EMail                 string `json:"EMail"`
	MarketerEaRole        string `json:"“MarketerEaRole”"`
	OwnerRole             string `json:"OwnerRole"`
	OrgName               string `json:"OrgName"`
}

type AccountStruct struct {
	AccountNumber              string `json:"AccountNumber"`
	PolicyPrefix               string `json:"PolicyPrefix"`
	InternalAccountName        string `json:"InternalAccountName"`
	AccountStatus              string `json:"AccountStatus"`
	AccountStatusEffectiveDate string `json:"AccountStatusEffectiveDate"`
	ValidationStatus           string `json:"ValidationStatus"`
	AccountEffectiveDate       string `json:"AccountEffectiveDate"`
	MarketerProduct            string `json:"MarketerProduct"`
	DisclosureStatus           string `json:"DisclosureStatus"`
	DisclosureEffectiveDate    string `json:"DisclosureEffectiveDate"`
}

type AssignmentStruct struct {
	AssignmentId            string `json:"AssignmentId"`
	AssignmentRoleType      string `json:"AssignmentRoleType"`
	SplitPercentage         string `json:"SplitPercentage"`
	AssignmentEffectiveDate string `json:"AssignmentEffectiveDate"`
	AssignmentStatus        string `json:"AssignmentStatus"`
	AssignmentEndDate       string `json:"AssignmentEndDate"`
	SplitEffectiveDate      string `json:"SplitEffectiveDate"`
	OwnerEId                string `json:"OwnerEId"`
	OwnerRole               string `json:"OwnerRole"`
	OrgName                 string `json:"OrgName"`
	policyPrefix            string `json:"policyPrefix"`
	accountNumber           string `json:"accountNumber"`
	EId                     string `json:"EId"`
	TaxId                   string `json:"TaxId"`
	BeginDate               string `json:"BeginDate"`
	MarketerTypeFlag        string `json:"MarketerTypeFlag"`
	MarketerType            string `json:"MarketerType"`
	MarketerRole            string `json:"MarketerRole"`
	MarketerStatus          string `json:"MarketerStatus"`
	LegalName               string `json:"LegalName"`
	Gender                  string `json:"Gender"`
	DoB                     string `json:"DoB"`
	RegStateName            string `json:"RegStateName"`
	MarketerEffectiveDate   string `json:"MarketerEffectiveDate"`
	MarketerEndDate         string `json:"MarketerEndDate"`
	FirstName               string `json:"FirstName"`
	LastName                string `json:"LastName"`
	EMail                   string `json:"EMail"`
	MarketerEaRole          string `json:"“MarketerEaRole”"`
}

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

func main() {
	err := shim.Start(new(SimpleChaincode))

	fmt.Println("****** Starting to send information to my ledger")

	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	err := stub.PutState("hello_world", []byte(args[0]))

	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "write" {
		return t.write(stub, args)
	} else if function == "account" {
		return t.account(stub, args)
	} else if function == "assign" {
		return t.assign(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation: " + function)
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	// Handle different functions
	if function == "read" { //read a variable
		return t.read(stub, args)
	}

	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query: " + function)
}

// write - invoke function to write key/value pair
func (t *SimpleChaincode) write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	var key string
	var err error

	mktrStruct := MarketerStruct{
		EId:                   args[0],
		TaxId:                 args[1],
		BeginDate:             args[2],
		MarketerTypeFlag:      args[3],
		MarketerType:          args[4],
		MarketerRole:          args[5],
		MarketerStatus:        args[6],
		LegalName:             args[7],
		Gender:                args[8],
		DoB:                   args[9],
		RegStateName:          args[10],
		MarketerEffectiveDate: args[11],
		MarketerEndDate:       args[12],
		FirstName:             args[13],
		LastName:              args[14],
		BusinessAddress:       args[15],
		City:                  args[16],
		State:                 args[17],
		PostalCode:            args[18],
		PhoneNumber:           args[19],
		EMail:                 args[20],
		MarketerEaRole:        args[21],
		OwnerRole:             args[22],
		OrgName:               args[23],
	}

	mktrStructBytes, err := json.Marshal(mktrStruct)
	_ = err //ignore errors
	key = args[0]
	//t.read(stub, args)
	isval, err := t.read(stub, args)
	if isval == nil {
		stub.PutState(key, mktrStructBytes)
		fmt.Println("*** successfully wrote marketer to state")
	} else {
		fmt.Println("****duplicate entry")
		dupMktrArr := []byte("Marketer exists!")
		return dupMktrArr, errors.New("duplicate entry")
	}

	successMsgArr := []byte("Marketer added succesfully!")

	return successMsgArr, nil
}

func (t *SimpleChaincode) account(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	var key string
	var err error

	accStruct := AccountStruct{
		AccountNumber:              args[0],
		PolicyPrefix:               args[1],
		InternalAccountName:        args[2],
		AccountStatus:              args[3],
		AccountStatusEffectiveDate: args[4],
		ValidationStatus:           args[5],
		AccountEffectiveDate:       args[6],
		MarketerProduct:            args[7],
		DisclosureStatus:           args[8],
		DisclosureEffectiveDate:    args[9],
	}

	accStructBytes, err := json.Marshal(accStruct)
	_ = err //ignore errors
	key = args[0]
	stub.PutState(key, accStructBytes)
	fmt.Println("*** successfully wrote account to state")

	successMsgArr := []byte("Account added succesfully!")

	return successMsgArr, nil
}

func (t *SimpleChaincode) assign(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	var key string
	var err error

	assignStruct := AssignmentStruct{
		AssignmentId:            args[0],
		AssignmentRoleType:      args[1],
		SplitPercentage:         args[2],
		AssignmentEffectiveDate: args[3],
		AssignmentStatus:        args[4],
		AssignmentEndDate:       args[5],
		SplitEffectiveDate:      args[6],
		OwnerEId:                args[7],
		OwnerRole:               args[8],
		OrgName:                 args[9],
		policyPrefix:            args[10],
		accountNumber:           args[11],
		EId:                     args[12],
		TaxId:                   args[13],
		BeginDate:               args[14],
		MarketerTypeFlag:        args[15],
		MarketerType:            args[16],
		MarketerRole:            args[17],
		MarketerStatus:          args[18],
		LegalName:               args[19],
		Gender:                  args[20],
		DoB:                     args[21],
		RegStateName:            args[22],
		MarketerEffectiveDate:   args[23],
		MarketerEndDate:         args[24],
		FirstName:               args[25],
		LastName:                args[26],
		EMail:                   args[27],
		MarketerEaRole:          args[28],
	}

	assignStructBytes, err := json.Marshal(assignStruct)
	_ = err //ignore errors
	key = args[0]

	stub.PutState(key, assignStructBytes)
	fmt.Println("*** successfully wrote assignemt to state")

	successMsgArr := []byte("Assignment added succesfully!")

	return successMsgArr, nil
}

// read - query function to read key/value pair
func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	var key, jsonResp string
	var err error

	var retrievedStruct MarketerStruct
	key = args[0]
	retrievedBytes, err := stub.GetState(key)
	json.Unmarshal(retrievedBytes, retrievedStruct)

	fmt.Println("Retrieved struct: ", retrievedStruct)

	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
		return nil, errors.New(jsonResp)
	}

	return retrievedBytes, nil
}
<commit_msg>making the json values camel-case<commit_after>/*
Copyright IBM Corp 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
		 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"encoding/json"
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type isval []byte

type MarketerStruct struct {
	EId                   string `json:"EId"`
	TaxId                 string `json:"TaxId"`
	BeginDate             string `json:"BeginDate"`
	MarketerTypeFlag      string `json:"MarketerTypeFlag"`
	MarketerType          string `json:"MarketerType"`
	MarketerRole          string `json:"MarketerRole"`
	MarketerStatus        string `json:"MarketerStatus"`
	LegalName             string `json:"LegalName"`
	Gender                string `json:"Gender"`
	DoB                   string `json:"DoB"`
	RegStateName          string `json:"RegStateName"`
	MarketerEffectiveDate string `json:"MarketerEffectiveDate"`
	MarketerEndDate       string `json:"MarketerEndDate"`
	FirstName             string `json:"FirstName"`
	LastName              string `json:"LastName"`
	BusinessAddress       string `json:"BusinessAddress"`
	City                  string `json:"City"`
	State                 string `json:"State"`
	PostalCode            string `json:"PostalCode"`
	PhoneNumber           string `json:"PhoneNumber"`
	EMail                 string `json:"EMail"`
	MarketerEaRole        string `json:"“MarketerEaRole”"`
	OwnerRole             string `json:"OwnerRole"`
	OrgName               string `json:"OrgName"`
}

type AccountStruct struct {
	AccountNumber              string `json:"accountNumber"`
	PolicyPrefix               string `json:"policyPrefix"`
	InternalAccountName        string `json:"internalAccountName"`
	AccountStatus              string `json:"accountStatus"`
	AccountStatusEffectiveDate string `json:"accountStatusEffectiveDate"`
	ValidationStatus           string `json:"validationStatus"`
	AccountEffectiveDate       string `json:"accountEffectiveDate"`
	MarketerProduct            string `json:"arketerProduct"`
	DisclosureStatus           string `json:"disclosureStatus"`
	DisclosureEffectiveDate    string `json:"disclosureEffectiveDate"`
}

type AssignmentStruct struct {
	AssignmentId            string `json:"AssignmentId"`
	AssignmentRoleType      string `json:"AssignmentRoleType"`
	SplitPercentage         string `json:"SplitPercentage"`
	AssignmentEffectiveDate string `json:"AssignmentEffectiveDate"`
	AssignmentStatus        string `json:"AssignmentStatus"`
	AssignmentEndDate       string `json:"AssignmentEndDate"`
	SplitEffectiveDate      string `json:"SplitEffectiveDate"`
	OwnerEId                string `json:"OwnerEId"`
	OwnerRole               string `json:"OwnerRole"`
	OrgName                 string `json:"OrgName"`
	policyPrefix            string `json:"policyPrefix"`
	accountNumber           string `json:"accountNumber"`
	EId                     string `json:"EId"`
	TaxId                   string `json:"TaxId"`
	BeginDate               string `json:"BeginDate"`
	MarketerTypeFlag        string `json:"MarketerTypeFlag"`
	MarketerType            string `json:"MarketerType"`
	MarketerRole            string `json:"MarketerRole"`
	MarketerStatus          string `json:"MarketerStatus"`
	LegalName               string `json:"LegalName"`
	Gender                  string `json:"Gender"`
	DoB                     string `json:"DoB"`
	RegStateName            string `json:"RegStateName"`
	MarketerEffectiveDate   string `json:"MarketerEffectiveDate"`
	MarketerEndDate         string `json:"MarketerEndDate"`
	FirstName               string `json:"FirstName"`
	LastName                string `json:"LastName"`
	EMail                   string `json:"EMail"`
	MarketerEaRole          string `json:"“MarketerEaRole”"`
}

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

func main() {
	err := shim.Start(new(SimpleChaincode))

	fmt.Println("****** Starting to send information to my ledger")

	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	err := stub.PutState("hello_world", []byte(args[0]))

	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "write" {
		return t.write(stub, args)
	} else if function == "account" {
		return t.account(stub, args)
	} else if function == "assign" {
		return t.assign(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation: " + function)
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	// Handle different functions
	if function == "read" { //read a variable
		return t.read(stub, args)
	}

	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query: " + function)
}

// write - invoke function to write key/value pair
func (t *SimpleChaincode) write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	var key string
	var err error

	mktrStruct := MarketerStruct{
		EId:                   args[0],
		TaxId:                 args[1],
		BeginDate:             args[2],
		MarketerTypeFlag:      args[3],
		MarketerType:          args[4],
		MarketerRole:          args[5],
		MarketerStatus:        args[6],
		LegalName:             args[7],
		Gender:                args[8],
		DoB:                   args[9],
		RegStateName:          args[10],
		MarketerEffectiveDate: args[11],
		MarketerEndDate:       args[12],
		FirstName:             args[13],
		LastName:              args[14],
		BusinessAddress:       args[15],
		City:                  args[16],
		State:                 args[17],
		PostalCode:            args[18],
		PhoneNumber:           args[19],
		EMail:                 args[20],
		MarketerEaRole:        args[21],
		OwnerRole:             args[22],
		OrgName:               args[23],
	}

	mktrStructBytes, err := json.Marshal(mktrStruct)
	_ = err //ignore errors
	key = args[0]
	//t.read(stub, args)
	isval, err := t.read(stub, args)
	if isval == nil {
		stub.PutState(key, mktrStructBytes)
		fmt.Println("*** successfully wrote marketer to state")
	} else {
		fmt.Println("****duplicate entry")
		dupMktrArr := []byte("Marketer exists!")
		return dupMktrArr, errors.New("duplicate entry")
	}

	successMsgArr := []byte("Marketer added succesfully!")

	return successMsgArr, nil
}

func (t *SimpleChaincode) account(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	var key string
	var err error

	accStruct := AccountStruct{
		AccountNumber:              args[0],
		PolicyPrefix:               args[1],
		InternalAccountName:        args[2],
		AccountStatus:              args[3],
		AccountStatusEffectiveDate: args[4],
		ValidationStatus:           args[5],
		AccountEffectiveDate:       args[6],
		MarketerProduct:            args[7],
		DisclosureStatus:           args[8],
		DisclosureEffectiveDate:    args[9],
	}

	accStructBytes, err := json.Marshal(accStruct)
	_ = err //ignore errors
	key = args[0]
	stub.PutState(key, accStructBytes)
	fmt.Println("*** successfully wrote account to state")

	successMsgArr := []byte("Account added succesfully!")

	return successMsgArr, nil
}

func (t *SimpleChaincode) assign(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	var key string
	var err error

	assignStruct := AssignmentStruct{
		AssignmentId:            args[0],
		AssignmentRoleType:      args[1],
		SplitPercentage:         args[2],
		AssignmentEffectiveDate: args[3],
		AssignmentStatus:        args[4],
		AssignmentEndDate:       args[5],
		SplitEffectiveDate:      args[6],
		OwnerEId:                args[7],
		OwnerRole:               args[8],
		OrgName:                 args[9],
		policyPrefix:            args[10],
		accountNumber:           args[11],
		EId:                     args[12],
		TaxId:                   args[13],
		BeginDate:               args[14],
		MarketerTypeFlag:        args[15],
		MarketerType:            args[16],
		MarketerRole:            args[17],
		MarketerStatus:          args[18],
		LegalName:               args[19],
		Gender:                  args[20],
		DoB:                     args[21],
		RegStateName:            args[22],
		MarketerEffectiveDate:   args[23],
		MarketerEndDate:         args[24],
		FirstName:               args[25],
		LastName:                args[26],
		EMail:                   args[27],
		MarketerEaRole:          args[28],
	}

	assignStructBytes, err := json.Marshal(assignStruct)
	_ = err //ignore errors
	key = args[0]

	stub.PutState(key, assignStructBytes)
	fmt.Println("*** successfully wrote assignemt to state")

	successMsgArr := []byte("Assignment added succesfully!")

	return successMsgArr, nil
}

// read - query function to read key/value pair
func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	var key, jsonResp string
	var err error

	var retrievedStruct MarketerStruct
	key = args[0]
	retrievedBytes, err := stub.GetState(key)
	json.Unmarshal(retrievedBytes, retrievedStruct)

	fmt.Println("Retrieved struct: ", retrievedStruct)

	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
		return nil, errors.New(jsonResp)
	}

	return retrievedBytes, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Ceph-CSI 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 cephfs

import (
	"context"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"sync"

	"github.com/ceph/ceph-csi/internal/util"
)

const (
	volumeMounterFuse   = "fuse"
	volumeMounterKernel = "kernel"
	netDev              = "_netdev"
)

var (
	availableMounters []string

	// maps a mountpoint to PID of its FUSE daemon
	fusePidMap    = make(map[string]int)
	fusePidMapMtx sync.Mutex

	fusePidRx = regexp.MustCompile(`(?m)^ceph-fuse\[(.+)\]: starting fuse$`)

	// nolint:gomnd // numbers specify Kernel versions.
	quotaSupport = []util.KernelVersion{
		{
			Version:      4,
			PatchLevel:   17,
			SubLevel:     0,
			ExtraVersion: 0, Distribution: "",
			Backport: false,
		}, // standard 4.17+ versions
		{
			Version:      3,
			PatchLevel:   10,
			SubLevel:     0,
			ExtraVersion: 1062,
			Distribution: ".el7",
			Backport:     true,
		}, // RHEL-7.7
	}
)

// Load available ceph mounters installed on system into availableMounters
// Called from driver.go's Run().
func loadAvailableMounters(conf *util.Config) error {
	// #nosec
	fuseMounterProbe := exec.Command("ceph-fuse", "--version")
	// #nosec
	kernelMounterProbe := exec.Command("mount.ceph")

	err := kernelMounterProbe.Run()
	if err != nil {
		util.ErrorLogMsg("failed to run mount.ceph %v", err)
	} else {
		// fetch the current running kernel info
		release, kvErr := util.GetKernelVersion()
		if kvErr != nil {
			return kvErr
		}

		if conf.ForceKernelCephFS || util.CheckKernelSupport(release, quotaSupport) {
			util.DefaultLog("loaded mounter: %s", volumeMounterKernel)
			availableMounters = append(availableMounters, volumeMounterKernel)
		} else {
			util.DefaultLog("kernel version < 4.17 might not support quota feature, hence not loading kernel client")
		}
	}

	err = fuseMounterProbe.Run()
	if err != nil {
		util.ErrorLogMsg("failed to run ceph-fuse %v", err)
	} else {
		util.DefaultLog("loaded mounter: %s", volumeMounterFuse)
		availableMounters = append(availableMounters, volumeMounterFuse)
	}

	if len(availableMounters) == 0 {
		return errors.New("no ceph mounters found on system")
	}

	return nil
}

type volumeMounter interface {
	mount(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error
	name() string
}

func newMounter(volOptions *volumeOptions) (volumeMounter, error) {
	// Get the mounter from the configuration

	wantMounter := volOptions.Mounter

	// Verify that it's available

	var chosenMounter string

	for _, availMounter := range availableMounters {
		if availMounter == wantMounter {
			chosenMounter = wantMounter
			break
		}
	}

	if chosenMounter == "" {
		// Otherwise pick whatever is left
		chosenMounter = availableMounters[0]
		util.DebugLogMsg("requested mounter: %s, chosen mounter: %s", wantMounter, chosenMounter)
	}

	// Create the mounter

	switch chosenMounter {
	case volumeMounterFuse:
		return &fuseMounter{}, nil
	case volumeMounterKernel:
		return &kernelMounter{}, nil
	}

	return nil, fmt.Errorf("unknown mounter '%s'", chosenMounter)
}

type fuseMounter struct{}

func mountFuse(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error {
	args := []string{
		mountPoint,
		"-m", volOptions.Monitors,
		"-c", util.CephConfigPath,
		"-n", cephEntityClientPrefix + cr.ID, "--keyfile=" + cr.KeyFile,
		"-r", volOptions.RootPath,
	}

	fmo := "nonempty"
	if volOptions.FuseMountOptions != "" {
		fmo += "," + strings.TrimSpace(volOptions.FuseMountOptions)
	}
	args = append(args, "-o", fmo)

	if volOptions.FsName != "" {
		args = append(args, "--client_mds_namespace="+volOptions.FsName)
	}

	_, stderr, err := util.ExecCommand(ctx, "ceph-fuse", args[:]...)
	if err != nil {
		return err
	}

	// Parse the output:
	// We need "starting fuse" meaning the mount is ok
	// and PID of the ceph-fuse daemon for unmount

	match := fusePidRx.FindSubmatch([]byte(stderr))
	// validMatchLength is set to 2 as match is expected
	// to have 2 items, starting fuse and PID of the fuse daemon
	const validMatchLength = 2
	if len(match) != validMatchLength {
		return fmt.Errorf("ceph-fuse failed: %s", stderr)
	}

	pid, err := strconv.Atoi(string(match[1]))
	if err != nil {
		return fmt.Errorf("failed to parse FUSE daemon PID: %w", err)
	}

	fusePidMapMtx.Lock()
	fusePidMap[mountPoint] = pid
	fusePidMapMtx.Unlock()

	return nil
}

func (m *fuseMounter) mount(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error {
	if err := util.CreateMountPoint(mountPoint); err != nil {
		return err
	}

	return mountFuse(ctx, mountPoint, cr, volOptions)
}

func (m *fuseMounter) name() string { return "Ceph FUSE driver" }

type kernelMounter struct{}

func mountKernel(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error {
	if err := execCommandErr(ctx, "modprobe", "ceph"); err != nil {
		return err
	}

	args := []string{
		"-t", "ceph",
		fmt.Sprintf("%s:%s", volOptions.Monitors, volOptions.RootPath),
		mountPoint,
	}

	optionsStr := fmt.Sprintf("name=%s,secretfile=%s", cr.ID, cr.KeyFile)
	mdsNamespace := ""
	if volOptions.FsName != "" {
		mdsNamespace = fmt.Sprintf("mds_namespace=%s", volOptions.FsName)
	}
	optionsStr = util.MountOptionsAdd(optionsStr, mdsNamespace, volOptions.KernelMountOptions, netDev)

	args = append(args, "-o", optionsStr)

	return execCommandErr(ctx, "mount", args[:]...)
}

func (m *kernelMounter) mount(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error {
	if err := util.CreateMountPoint(mountPoint); err != nil {
		return err
	}

	return mountKernel(ctx, mountPoint, cr, volOptions)
}

func (m *kernelMounter) name() string { return "Ceph kernel client" }

func bindMount(ctx context.Context, from, to string, readOnly bool, mntOptions []string) error {
	mntOptionSli := strings.Join(mntOptions, ",")
	if err := execCommandErr(ctx, "mount", "-o", mntOptionSli, from, to); err != nil {
		return fmt.Errorf("failed to bind-mount %s to %s: %w", from, to, err)
	}

	if readOnly {
		mntOptionSli = util.MountOptionsAdd(mntOptionSli, "remount")
		if err := execCommandErr(ctx, "mount", "-o", mntOptionSli, to); err != nil {
			return fmt.Errorf("failed read-only remount of %s: %w", to, err)
		}
	}

	return nil
}

func unmountVolume(ctx context.Context, mountPoint string) error {
	if err := execCommandErr(ctx, "umount", mountPoint); err != nil {
		if strings.Contains(err.Error(), fmt.Sprintf("exit status 32: umount: %s: not mounted", mountPoint)) ||
			strings.Contains(err.Error(), "No such file or directory") {
			return nil
		}
		return err
	}

	fusePidMapMtx.Lock()
	pid, ok := fusePidMap[mountPoint]
	if ok {
		delete(fusePidMap, mountPoint)
	}
	fusePidMapMtx.Unlock()

	if ok {
		p, err := os.FindProcess(pid)
		if err != nil {
			util.WarningLog(ctx, "failed to find process %d: %v", pid, err)
		} else {
			if _, err = p.Wait(); err != nil {
				util.WarningLog(ctx, "%d is not a child process: %v", pid, err)
			}
		}
	}

	return nil
}
<commit_msg>cephfs: fix unmountVolume function<commit_after>/*
Copyright 2018 The Ceph-CSI 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 cephfs

import (
	"context"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"sync"

	"github.com/ceph/ceph-csi/internal/util"
)

const (
	volumeMounterFuse   = "fuse"
	volumeMounterKernel = "kernel"
	netDev              = "_netdev"
)

var (
	availableMounters []string

	// maps a mountpoint to PID of its FUSE daemon
	fusePidMap    = make(map[string]int)
	fusePidMapMtx sync.Mutex

	fusePidRx = regexp.MustCompile(`(?m)^ceph-fuse\[(.+)\]: starting fuse$`)

	// nolint:gomnd // numbers specify Kernel versions.
	quotaSupport = []util.KernelVersion{
		{
			Version:      4,
			PatchLevel:   17,
			SubLevel:     0,
			ExtraVersion: 0, Distribution: "",
			Backport: false,
		}, // standard 4.17+ versions
		{
			Version:      3,
			PatchLevel:   10,
			SubLevel:     0,
			ExtraVersion: 1062,
			Distribution: ".el7",
			Backport:     true,
		}, // RHEL-7.7
	}
)

// Load available ceph mounters installed on system into availableMounters
// Called from driver.go's Run().
func loadAvailableMounters(conf *util.Config) error {
	// #nosec
	fuseMounterProbe := exec.Command("ceph-fuse", "--version")
	// #nosec
	kernelMounterProbe := exec.Command("mount.ceph")

	err := kernelMounterProbe.Run()
	if err != nil {
		util.ErrorLogMsg("failed to run mount.ceph %v", err)
	} else {
		// fetch the current running kernel info
		release, kvErr := util.GetKernelVersion()
		if kvErr != nil {
			return kvErr
		}

		if conf.ForceKernelCephFS || util.CheckKernelSupport(release, quotaSupport) {
			util.DefaultLog("loaded mounter: %s", volumeMounterKernel)
			availableMounters = append(availableMounters, volumeMounterKernel)
		} else {
			util.DefaultLog("kernel version < 4.17 might not support quota feature, hence not loading kernel client")
		}
	}

	err = fuseMounterProbe.Run()
	if err != nil {
		util.ErrorLogMsg("failed to run ceph-fuse %v", err)
	} else {
		util.DefaultLog("loaded mounter: %s", volumeMounterFuse)
		availableMounters = append(availableMounters, volumeMounterFuse)
	}

	if len(availableMounters) == 0 {
		return errors.New("no ceph mounters found on system")
	}

	return nil
}

type volumeMounter interface {
	mount(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error
	name() string
}

func newMounter(volOptions *volumeOptions) (volumeMounter, error) {
	// Get the mounter from the configuration

	wantMounter := volOptions.Mounter

	// Verify that it's available

	var chosenMounter string

	for _, availMounter := range availableMounters {
		if availMounter == wantMounter {
			chosenMounter = wantMounter
			break
		}
	}

	if chosenMounter == "" {
		// Otherwise pick whatever is left
		chosenMounter = availableMounters[0]
		util.DebugLogMsg("requested mounter: %s, chosen mounter: %s", wantMounter, chosenMounter)
	}

	// Create the mounter

	switch chosenMounter {
	case volumeMounterFuse:
		return &fuseMounter{}, nil
	case volumeMounterKernel:
		return &kernelMounter{}, nil
	}

	return nil, fmt.Errorf("unknown mounter '%s'", chosenMounter)
}

type fuseMounter struct{}

func mountFuse(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error {
	args := []string{
		mountPoint,
		"-m", volOptions.Monitors,
		"-c", util.CephConfigPath,
		"-n", cephEntityClientPrefix + cr.ID, "--keyfile=" + cr.KeyFile,
		"-r", volOptions.RootPath,
	}

	fmo := "nonempty"
	if volOptions.FuseMountOptions != "" {
		fmo += "," + strings.TrimSpace(volOptions.FuseMountOptions)
	}
	args = append(args, "-o", fmo)

	if volOptions.FsName != "" {
		args = append(args, "--client_mds_namespace="+volOptions.FsName)
	}

	_, stderr, err := util.ExecCommand(ctx, "ceph-fuse", args[:]...)
	if err != nil {
		return err
	}

	// Parse the output:
	// We need "starting fuse" meaning the mount is ok
	// and PID of the ceph-fuse daemon for unmount

	match := fusePidRx.FindSubmatch([]byte(stderr))
	// validMatchLength is set to 2 as match is expected
	// to have 2 items, starting fuse and PID of the fuse daemon
	const validMatchLength = 2
	if len(match) != validMatchLength {
		return fmt.Errorf("ceph-fuse failed: %s", stderr)
	}

	pid, err := strconv.Atoi(string(match[1]))
	if err != nil {
		return fmt.Errorf("failed to parse FUSE daemon PID: %w", err)
	}

	fusePidMapMtx.Lock()
	fusePidMap[mountPoint] = pid
	fusePidMapMtx.Unlock()

	return nil
}

func (m *fuseMounter) mount(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error {
	if err := util.CreateMountPoint(mountPoint); err != nil {
		return err
	}

	return mountFuse(ctx, mountPoint, cr, volOptions)
}

func (m *fuseMounter) name() string { return "Ceph FUSE driver" }

type kernelMounter struct{}

func mountKernel(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error {
	if err := execCommandErr(ctx, "modprobe", "ceph"); err != nil {
		return err
	}

	args := []string{
		"-t", "ceph",
		fmt.Sprintf("%s:%s", volOptions.Monitors, volOptions.RootPath),
		mountPoint,
	}

	optionsStr := fmt.Sprintf("name=%s,secretfile=%s", cr.ID, cr.KeyFile)
	mdsNamespace := ""
	if volOptions.FsName != "" {
		mdsNamespace = fmt.Sprintf("mds_namespace=%s", volOptions.FsName)
	}
	optionsStr = util.MountOptionsAdd(optionsStr, mdsNamespace, volOptions.KernelMountOptions, netDev)

	args = append(args, "-o", optionsStr)

	return execCommandErr(ctx, "mount", args[:]...)
}

func (m *kernelMounter) mount(ctx context.Context, mountPoint string, cr *util.Credentials, volOptions *volumeOptions) error {
	if err := util.CreateMountPoint(mountPoint); err != nil {
		return err
	}

	return mountKernel(ctx, mountPoint, cr, volOptions)
}

func (m *kernelMounter) name() string { return "Ceph kernel client" }

func bindMount(ctx context.Context, from, to string, readOnly bool, mntOptions []string) error {
	mntOptionSli := strings.Join(mntOptions, ",")
	if err := execCommandErr(ctx, "mount", "-o", mntOptionSli, from, to); err != nil {
		return fmt.Errorf("failed to bind-mount %s to %s: %w", from, to, err)
	}

	if readOnly {
		mntOptionSli = util.MountOptionsAdd(mntOptionSli, "remount")
		if err := execCommandErr(ctx, "mount", "-o", mntOptionSli, to); err != nil {
			return fmt.Errorf("failed read-only remount of %s: %w", to, err)
		}
	}

	return nil
}

func unmountVolume(ctx context.Context, mountPoint string) error {
	if _, stderr, err := util.ExecCommand(ctx, "umount", mountPoint); err != nil {
		err = fmt.Errorf("%w stderr: %s", err, stderr)
		if strings.Contains(err.Error(), fmt.Sprintf("umount: %s: not mounted", mountPoint)) ||
			strings.Contains(err.Error(), "No such file or directory") {
			return nil
		}
		return err
	}

	fusePidMapMtx.Lock()
	pid, ok := fusePidMap[mountPoint]
	if ok {
		delete(fusePidMap, mountPoint)
	}
	fusePidMapMtx.Unlock()

	if ok {
		p, err := os.FindProcess(pid)
		if err != nil {
			util.WarningLog(ctx, "failed to find process %d: %v", pid, err)
		} else {
			if _, err = p.Wait(); err != nil {
				util.WarningLog(ctx, "%d is not a child process: %v", pid, err)
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2016 e-Xpert Solutions SA. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ltm

import (
	"encoding/json"
	"net/http"

	"github.com/e-XpertSolutions/f5-rest-client/f5"
)

// VirtualServerConfigList holds a list of virtual server configuration.
type VirtualServerConfigList struct {
	Items    []VirtualServerConfig `json:"items,omitempty"`
	Kind     string                `json:"kind,omitempty"`
	SelfLink string                `json:"selfLink,omitempty"`
}

// VirtualServerConfig holds the configuration of a single virtual server.
type VirtualServerConfig struct {
	AddressStatus     string `json:"addressStatus,omitempty"`
	AutoLasthop       string `json:"autoLasthop,omitempty"`
	CmpEnabled        string `json:"cmpEnabled,omitempty"`
	ConnectionLimit   int64  `json:"connectionLimit,omitempty"`
	Description       string `json:"description,omitempty"`
	Destination       string `json:"destination,omitempty"`
	Disabled          bool   `json:"disabled,omitempty"`
	Enabled           bool   `json:"enabled,omitempty"`
	FullPath          string `json:"fullPath,omitempty"`
	Generation        int64  `json:"generation,omitempty"`
	GtmScore          int64  `json:"gtmScore,omitempty"`
	IPProtocol        string `json:"ipProtocol,omitempty"`
	Kind              string `json:"kind,omitempty"`
	Mask              string `json:"mask,omitempty"`
	Mirror            string `json:"mirror,omitempty"`
	MobileAppTunnel   string `json:"mobileAppTunnel,omitempty"`
	Name              string `json:"name,omitempty"`
	Nat64             string `json:"nat64,omitempty"`
	Partition         string `json:"partition,omitempty"`
	PoliciesReference struct {
		IsSubcollection bool   `json:"isSubcollection,omitempty"`
		Link            string `json:"link,omitempty"`
	} `json:"policiesReference,omitempty"`
	Pool              string `json:"pool,omitempty"`
	ProfilesReference struct {
		IsSubcollection bool   `json:"isSubcollection,omitempty"`
		Link            string `json:"link,omitempty"`
	} `json:"profilesReference,omitempty"`
	RateLimit                string   `json:"rateLimit,omitempty"`
	RateLimitDstMask         int64    `json:"rateLimitDstMask,omitempty"`
	RateLimitMode            string   `json:"rateLimitMode,omitempty"`
	RateLimitSrcMask         int64    `json:"rateLimitSrcMask,omitempty"`
	Rules                    []string `json:"rules,omitempty"`
	SelfLink                 string   `json:"selfLink,omitempty"`
	Source                   string   `json:"source,omitempty"`
	SourceAddressTranslation struct {
		Type string `json:"type,omitempty"`
	} `json:"sourceAddressTranslation,omitempty"`
	SourcePort       string   `json:"sourcePort,omitempty"`
	SynCookieStatus  string   `json:"synCookieStatus,omitempty"`
	TranslateAddress string   `json:"translateAddress,omitempty"`
	TranslatePort    string   `json:"translatePort,omitempty"`
	Vlans            []string `json:"vlans,omitempty"`
	VlansDisabled    bool     `json:"vlansDisabled,omitempty"`
	VlansEnabled     bool     `json:"vlansEnabled,omitempty"`
	VsIndex          int64    `json:"vsIndex,omitempty"`
}

// VirtualEndpoint represents the REST resource for managing virtual server.
const VirtualEndpoint = "/virtual"

// VirtualResponse provide a simple mechanism to read paginated results.
//
// TODO(gilliek): use VirtualResponse object where pagination is needed.
type VirtualResponse struct {
}

// VirtualResource provides an API to manage virtual server configurations.
type VirtualResource struct {
	c *f5.Client
}

// ListAll lists all the virtual server configurations.
func (vr *VirtualResource) ListAll() (*VirtualServerConfigList, error) {
	resp, err := vr.doRequest("GET", "", nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return nil, err
	}
	var vsc VirtualServerConfigList
	dec := json.NewDecoder(resp.Body)
	if err := dec.Decode(&vsc); err != nil {
		return nil, err
	}
	return &vsc, nil
}

// Get a single virtual server configuration identified by id.
func (vr *VirtualResource) Get(id string) (*VirtualServerConfig, error) {
	resp, err := vr.doRequest("GET", id, nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return nil, err
	}
	var vsci VirtualServerConfig
	dec := json.NewDecoder(resp.Body)
	if err := dec.Decode(&vsci); err != nil {
		return nil, err
	}
	return &vsci, nil
}

// Create a new virtual server configuration.
func (vr *VirtualResource) Create(item VirtualServerConfig) error {
	resp, err := vr.doRequest("POST", "", item)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Edit a virtual server configuration identified by id.
func (vr *VirtualResource) Edit(id string, item VirtualServerConfig) error {
	resp, err := vr.doRequest("PUT", id, item)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Enabling a virtual server item identified by id.
func (vr *VirtualResource) Enable(id string) error {
	item := VirtualServerConfig{Enabled: true}
	resp, err := vr.doRequest("PATCH", id, item)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Disabling a virtual server item identified by id.
func (vr *VirtualResource) Disable(id string) error {
	item := VirtualServerConfig{Disabled: true}
	resp, err := vr.doRequest("PATCH", id, item)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Delete a single server configuration identified by id.
func (vr *VirtualResource) Delete(id string) error {
	resp, err := vr.doRequest("DELETE", id, nil)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Rules gets the iRules configuration for a virtual server identified by id.
func (vr *VirtualResource) Rules(id string) ([]Rule, error) {
	resp, err := vr.doRequest("GET", id+"/rule", nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return nil, err
	}
	var rules []Rule
	dec := json.NewDecoder(resp.Body)
	if err := dec.Decode(&rules); err != nil {
		return nil, err
	}
	return rules, nil
}

// AddRule adds an iRule to the virtual server identified by id.
func (vr *VirtualResource) AddRule(id string, rule Rule) error {
	resp, err := vr.doRequest("POST", id+"/rule", rule)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// RemoveRule removes a single  iRule from the virtual server identified by id.
func (vr *VirtualResource) RemoveRule(vsID, ruleID string) error {
	resp, err := vr.doRequest("DELETE", vsID+"/rule/"+ruleID, nil)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// doRequest creates and send HTTP request using the F5 client.
//
// TODO(gilliek): decorate errors
func (vr *VirtualResource) doRequest(method, id string, data interface{}) (*http.Response, error) {
	req, err := vr.c.MakeRequest(method, BasePath+VirtualEndpoint+"/"+id, data)
	if err != nil {
		return nil, err
	}
	resp, err := vr.c.Do(req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// readError reads request error object from a HTTP response.
//
// TODO(gilliek): move this function into F5 package.
func (vr *VirtualResource) readError(resp *http.Response) error {
	if resp.StatusCode >= 400 {
		errResp, err := f5.NewRequestError(resp.Body)
		if err != nil {
			return err
		}
		return errResp
	}
	return nil
}
<commit_msg>f5/ltm: fix an issue with Create function that append an extra / to the request path<commit_after>// Copyright 2016 e-Xpert Solutions SA. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ltm

import (
	"encoding/json"
	"net/http"

	"github.com/e-XpertSolutions/f5-rest-client/f5"
)

// VirtualServerConfigList holds a list of virtual server configuration.
type VirtualServerConfigList struct {
	Items    []VirtualServerConfig `json:"items,omitempty"`
	Kind     string                `json:"kind,omitempty"`
	SelfLink string                `json:"selfLink,omitempty"`
}

// VirtualServerConfig holds the configuration of a single virtual server.
type VirtualServerConfig struct {
	AddressStatus     string `json:"addressStatus,omitempty"`
	AutoLasthop       string `json:"autoLasthop,omitempty"`
	CmpEnabled        string `json:"cmpEnabled,omitempty"`
	ConnectionLimit   int64  `json:"connectionLimit,omitempty"`
	Description       string `json:"description,omitempty"`
	Destination       string `json:"destination,omitempty"`
	Disabled          bool   `json:"disabled,omitempty"`
	Enabled           bool   `json:"enabled,omitempty"`
	FullPath          string `json:"fullPath,omitempty"`
	Generation        int64  `json:"generation,omitempty"`
	GtmScore          int64  `json:"gtmScore,omitempty"`
	IPProtocol        string `json:"ipProtocol,omitempty"`
	Kind              string `json:"kind,omitempty"`
	Mask              string `json:"mask,omitempty"`
	Mirror            string `json:"mirror,omitempty"`
	MobileAppTunnel   string `json:"mobileAppTunnel,omitempty"`
	Name              string `json:"name,omitempty"`
	Nat64             string `json:"nat64,omitempty"`
	Partition         string `json:"partition,omitempty"`
	PoliciesReference struct {
		IsSubcollection bool   `json:"isSubcollection,omitempty"`
		Link            string `json:"link,omitempty"`
	} `json:"policiesReference,omitempty"`
	Pool              string    `json:"pool,omitempty"`
	Profiles          []Profile `json:"profiles,omitempty"`
	ProfilesReference struct {
		IsSubcollection bool   `json:"isSubcollection,omitempty"`
		Link            string `json:"link,omitempty"`
	} `json:"profilesReference,omitempty"`
	RateLimit                string                   `json:"rateLimit,omitempty"`
	RateLimitDstMask         int64                    `json:"rateLimitDstMask,omitempty"`
	RateLimitMode            string                   `json:"rateLimitMode,omitempty"`
	RateLimitSrcMask         int64                    `json:"rateLimitSrcMask,omitempty"`
	Rules                    []string                 `json:"rules,omitempty"`
	SelfLink                 string                   `json:"selfLink,omitempty"`
	Source                   string                   `json:"source,omitempty"`
	SourceAddressTranslation SourceAddressTranslation `json:"sourceAddressTranslation,omitempty"`
	SourcePort               string                   `json:"sourcePort,omitempty"`
	SynCookieStatus          string                   `json:"synCookieStatus,omitempty"`
	TranslateAddress         string                   `json:"translateAddress,omitempty"`
	TranslatePort            string                   `json:"translatePort,omitempty"`
	Vlans                    []string                 `json:"vlans,omitempty"`
	VlansDisabled            bool                     `json:"vlansDisabled,omitempty"`
	VlansEnabled             bool                     `json:"vlansEnabled,omitempty"`
	VsIndex                  int64                    `json:"vsIndex,omitempty"`
}

type SourceAddressTranslation struct {
	Type string `json:"type,omitempty"`
}

type Profile struct {
	Name    string `json:"name,omitempty"`
	Context string `json:"context,omitempty"`
}

// VirtualEndpoint represents the REST resource for managing virtual server.
const VirtualEndpoint = "/virtual"

// VirtualResponse provide a simple mechanism to read paginated results.
//
// TODO(gilliek): use VirtualResponse object where pagination is needed.
type VirtualResponse struct {
}

// VirtualResource provides an API to manage virtual server configurations.
type VirtualResource struct {
	c *f5.Client
}

// ListAll lists all the virtual server configurations.
func (vr *VirtualResource) ListAll() (*VirtualServerConfigList, error) {
	resp, err := vr.doRequest("GET", "", nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return nil, err
	}
	var vsc VirtualServerConfigList
	dec := json.NewDecoder(resp.Body)
	if err := dec.Decode(&vsc); err != nil {
		return nil, err
	}
	return &vsc, nil
}

// Get a single virtual server configuration identified by id.
func (vr *VirtualResource) Get(id string) (*VirtualServerConfig, error) {
	resp, err := vr.doRequest("GET", id, nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return nil, err
	}
	var vsci VirtualServerConfig
	dec := json.NewDecoder(resp.Body)
	if err := dec.Decode(&vsci); err != nil {
		return nil, err
	}
	return &vsci, nil
}

// Create a new virtual server configuration.
func (vr *VirtualResource) Create(item VirtualServerConfig) error {
	if err := vr.c.ModQuery("POST", BasePath+VirtualEndpoint, item); err != nil {
		return err
	}
	return nil
}

// Edit a virtual server configuration identified by id.
func (vr *VirtualResource) Edit(id string, item VirtualServerConfig) error {
	resp, err := vr.doRequest("PUT", id, item)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Enabling a virtual server item identified by id.
func (vr *VirtualResource) Enable(id string) error {
	item := VirtualServerConfig{Enabled: true}
	resp, err := vr.doRequest("PATCH", id, item)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Disabling a virtual server item identified by id.
func (vr *VirtualResource) Disable(id string) error {
	item := VirtualServerConfig{Disabled: true}
	resp, err := vr.doRequest("PATCH", id, item)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Delete a single server configuration identified by id.
func (vr *VirtualResource) Delete(id string) error {
	resp, err := vr.doRequest("DELETE", id, nil)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// Rules gets the iRules configuration for a virtual server identified by id.
func (vr *VirtualResource) Rules(id string) ([]Rule, error) {
	resp, err := vr.doRequest("GET", id+"/rule", nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return nil, err
	}
	var rules []Rule
	dec := json.NewDecoder(resp.Body)
	if err := dec.Decode(&rules); err != nil {
		return nil, err
	}
	return rules, nil
}

// AddRule adds an iRule to the virtual server identified by id.
func (vr *VirtualResource) AddRule(id string, rule Rule) error {
	resp, err := vr.doRequest("POST", id+"/rule", rule)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// RemoveRule removes a single  iRule from the virtual server identified by id.
func (vr *VirtualResource) RemoveRule(vsID, ruleID string) error {
	resp, err := vr.doRequest("DELETE", vsID+"/rule/"+ruleID, nil)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := vr.readError(resp); err != nil {
		return err
	}
	return nil
}

// doRequest creates and send HTTP request using the F5 client.
//
// TODO(gilliek): decorate errors
func (vr *VirtualResource) doRequest(method, id string, data interface{}) (*http.Response, error) {
	req, err := vr.c.MakeRequest(method, BasePath+VirtualEndpoint+"/"+id, data)
	if err != nil {
		return nil, err
	}
	resp, err := vr.c.Do(req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// readError reads request error object from a HTTP response.
//
// TODO(gilliek): move this function into F5 package.
func (vr *VirtualResource) readError(resp *http.Response) error {
	if resp.StatusCode >= 400 {
		errResp, err := f5.NewRequestError(resp.Body)
		if err != nil {
			return err
		}
		return errResp
	}
	return nil
}
<|endoftext|>


<commit_before>package end2end_test

import (
	"fmt"
	"math/rand"
	"sync"
	"time"

	"golang.org/x/net/context"

	"github.com/apoydence/talaria/pb"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("End2end", func() {
	Context("Data has been written", func() {
		var (
			fileInfo *pb.File
		)

		var writeTo = func(name string, data []byte, writer pb.Talaria_WriteClient) {
			packet := &pb.WriteDataPacket{
				FileName: name,
				Message:  data,
			}
			Expect(writer.Send(packet)).To(Succeed())
		}

		var fetchReader = func(name string, client pb.TalariaClient) chan []byte {
			c := make(chan []byte, 100)

			fileInfo = &pb.File{
				FileName: name,
			}

			reader, err := client.Read(context.Background(), fileInfo)
			Expect(err).ToNot(HaveOccurred())

			go func() {
				for {
					packet, err := reader.Recv()
					if err != nil {
						return
					}
					c <- packet.Message
				}
			}()
			return c
		}

		var createFileName = func() string {
			return fmt.Sprintf("some-file-%d", rand.Int63())
		}

		var writeSlowly = func(count int, fileInfo *pb.File, writer pb.Talaria_WriteClient) *sync.WaitGroup {
			var wg sync.WaitGroup
			wg.Add(1)
			go func() {
				defer wg.Done()
				for i := 0; i < count; i++ {
					time.Sleep(time.Millisecond)
					writeTo(fileInfo.FileName, []byte(fmt.Sprintf("some-data-%d", i)), writer)
				}
			}()
			return &wg
		}

		BeforeEach(func() {
			fileInfo = &pb.File{
				FileName: createFileName(),
			}
			talariaClient.Create(context.Background(), fileInfo)
		})

		It("writes data to a subscriber", func() {
			writer, err := talariaClient.Write(context.Background())
			Expect(err).ToNot(HaveOccurred())
			writeTo(fileInfo.FileName, []byte("some-data-1"), writer)
			writeTo(fileInfo.FileName, []byte("some-data-2"), writer)

			data := fetchReader(fileInfo.FileName, talariaClient)
			Eventually(data).Should(Receive(Equal([]byte("some-data-1"))))
			Eventually(data).Should(Receive(Equal([]byte("some-data-2"))))
		})

		It("Read() tails", func() {
			data := fetchReader(fileInfo.FileName, talariaClient)
			writer, err := talariaClient.Write(context.Background())
			Expect(err).ToNot(HaveOccurred())

			wg := writeSlowly(10, fileInfo, writer)
			defer wg.Wait()

			for i := 0; i < 10; i++ {
				expectedData := []byte(fmt.Sprintf("some-data-%d", i))
				Eventually(data).Should(Receive(Equal(expectedData)))
			}
		})
	})
})
<commit_msg>Add end2end test ensuring files must be created<commit_after>package end2end_test

import (
	"fmt"
	"math/rand"
	"sync"
	"time"

	"golang.org/x/net/context"

	"github.com/apoydence/talaria/pb"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("End2end", func() {
	Context("Data has been written", func() {
		var (
			fileInfo *pb.File
		)

		var writeTo = func(name string, data []byte, writer pb.Talaria_WriteClient) {
			packet := &pb.WriteDataPacket{
				FileName: name,
				Message:  data,
			}
			Expect(writer.Send(packet)).To(Succeed())
		}

		var fetchReader = func(name string, client pb.TalariaClient) chan []byte {
			c := make(chan []byte, 100)

			fileInfo = &pb.File{
				FileName: name,
			}

			reader, err := client.Read(context.Background(), fileInfo)
			Expect(err).ToNot(HaveOccurred())

			go func() {
				for {
					packet, err := reader.Recv()
					if err != nil {
						return
					}
					c <- packet.Message
				}
			}()
			return c
		}

		var createFileName = func() string {
			return fmt.Sprintf("some-file-%d", rand.Int63())
		}

		var writeSlowly = func(count int, fileInfo *pb.File, writer pb.Talaria_WriteClient) *sync.WaitGroup {
			var wg sync.WaitGroup
			wg.Add(1)
			go func() {
				defer wg.Done()
				for i := 0; i < count; i++ {
					time.Sleep(time.Millisecond)
					writeTo(fileInfo.FileName, []byte(fmt.Sprintf("some-data-%d", i)), writer)
				}
			}()
			return &wg
		}

		BeforeEach(func() {
			fileInfo = &pb.File{
				FileName: createFileName(),
			}
		})

		Context("file has been created", func() {
			BeforeEach(func() {
				talariaClient.Create(context.Background(), fileInfo)
			})

			It("writes data to a subscriber", func() {
				writer, err := talariaClient.Write(context.Background())
				Expect(err).ToNot(HaveOccurred())
				writeTo(fileInfo.FileName, []byte("some-data-1"), writer)
				writeTo(fileInfo.FileName, []byte("some-data-2"), writer)

				data := fetchReader(fileInfo.FileName, talariaClient)
				Eventually(data).Should(Receive(Equal([]byte("some-data-1"))))
				Eventually(data).Should(Receive(Equal([]byte("some-data-2"))))
			})

			It("Read() tails", func() {
				data := fetchReader(fileInfo.FileName, talariaClient)
				writer, err := talariaClient.Write(context.Background())
				Expect(err).ToNot(HaveOccurred())

				wg := writeSlowly(10, fileInfo, writer)
				defer wg.Wait()

				for i := 0; i < 10; i++ {
					expectedData := []byte(fmt.Sprintf("some-data-%d", i))
					Eventually(data).Should(Receive(Equal(expectedData)))
				}
			})
		})

		Context("file has not been created", func() {
			It("returns an error", func() {
				writer, err := talariaClient.Write(context.Background())
				Expect(err).ToNot(HaveOccurred())

				_, err = writer.CloseAndRecv()
				Expect(err).To(HaveOccurred())
			})
		})
	})
})
<|endoftext|>