<commit_before>// Copyright 2022 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 git

import (
	"context"
	"fmt"
	"path"
	"time"

	"github.com/GoogleContainerTools/kpt/porch/api/porch/v1alpha1"
	"github.com/GoogleContainerTools/kpt/porch/repository/pkg/repository"
	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/config"
	"github.com/go-git/go-git/v5/plumbing"
)

type gitPackageDraft struct {
	parent    *gitRepository
	path      string
	revision  string
	lifecycle v1alpha1.PackageRevisionLifecycle // New value of the package revision lifecycle
	updated   time.Time
	base      *plumbing.Reference // ref to the base of the package update commit chain (used for conditional push)
	branch    BranchName          // name of the branch where the changes will be pushed
	commit    plumbing.Hash       // Current HEAD of the package changes (commit sha)
	tree      plumbing.Hash       // Cached tree of the package itself, some descendent of commit.Tree()
}

var _ repository.PackageDraft = &gitPackageDraft{}

func (d *gitPackageDraft) UpdateResources(ctx context.Context, new *v1alpha1.PackageRevisionResources, change *v1alpha1.Task) error {
	ch, err := newCommitHelper(d.parent.repo.Storer, d.parent.userInfoProvider, d.commit, d.path, plumbing.ZeroHash)
	if err != nil {
		return fmt.Errorf("failed to commit packgae: %w", err)
	}

	for k, v := range new.Spec.Resources {
		ch.storeFile(path.Join(d.path, k), v)
	}

	message := fmt.Sprintf("Intermittent commit: %s", change.Type)
	commitHash, packageTree, err := ch.commit(ctx, message, d.path)
	if err != nil {
		return fmt.Errorf("failed to commit package: %w", err)
	}

	d.tree = packageTree
	d.commit = commitHash
	return nil
}

func (d *gitPackageDraft) UpdateLifecycle(ctx context.Context, new v1alpha1.PackageRevisionLifecycle) error {
	d.lifecycle = new
	return nil
}

// Finish round of updates.
func (d *gitPackageDraft) Close(ctx context.Context) (repository.PackageRevision, error) {
	return d.parent.closeDraft(ctx, d)
}

func (r *gitRepository) closeDraft(ctx context.Context, d *gitPackageDraft) (*gitPackageRevision, error) {
	refSpecs := newPushRefSpecBuilder()
	draftBranch := createDraftName(d.path, d.revision)
	proposedBranch := createProposedName(d.path, d.revision)

	var newRef *plumbing.Reference

	switch d.lifecycle {
	case v1alpha1.PackageRevisionLifecycleFinal:
		// Finalize the package revision. Commit it to main branch.
		commitHash, newTreeHash, commitBase, err := r.commitPackageToMain(ctx, d)
		if err != nil {
			return nil, err
		}

		tag := createFinalTagNameInLocal(d.path, d.revision)
		refSpecs.AddRefToPush(commitHash, r.branch.RefInLocal()) // Push new main branch
		refSpecs.AddRefToPush(commitHash, tag)                   // Push the tag
		refSpecs.RequireRef(commitBase)                          // Make sure main didn't advance

		// Delete base branch (if one exists and should be deleted)
		switch base := d.base; {
		case base == nil: // no branch to delete
		case base.Name() == draftBranch.RefInLocal(), base.Name() == proposedBranch.RefInLocal():
			refSpecs.AddRefToDelete(base)
		}

		// Update package draft
		d.commit = commitHash
		d.tree = newTreeHash
		newRef = plumbing.NewHashReference(tag, commitHash)

	case v1alpha1.PackageRevisionLifecycleProposed:
		// Push the package revision into a proposed branch.
		refSpecs.AddRefToPush(d.commit, proposedBranch.RefInLocal())

		// Delete base branch (if one exists and should be deleted)
		switch base := d.base; {
		case base == nil: // no branch to delete
		case base.Name() != proposedBranch.RefInLocal():
			refSpecs.AddRefToDelete(base)
		}

		// Update package referemce (commit and tree hash stay the same)
		newRef = plumbing.NewHashReference(proposedBranch.RefInLocal(), d.commit)

	case v1alpha1.PackageRevisionLifecycleDraft:
		// Push the package revision into a draft branch.
		refSpecs.AddRefToPush(d.commit, draftBranch.RefInLocal())
		// Delete base branch (if one exists and should be deleted)
		switch base := d.base; {
		case base == nil: // no branch to delete
		case base.Name() != draftBranch.RefInLocal():
			refSpecs.AddRefToDelete(base)
		}

		// Update package referemce (commit and tree hash stay the same)
		newRef = plumbing.NewHashReference(draftBranch.RefInLocal(), d.commit)

	default:
		return nil, fmt.Errorf("package has unrecognized lifecycle: %q", d.lifecycle)
	}

	if err := d.parent.pushAndCleanup(ctx, refSpecs); err != nil {
		return nil, err
	}

	return &gitPackageRevision{
		parent:   d.parent,
		path:     d.path,
		revision: d.revision,
		updated:  d.updated,
		ref:      newRef,
		tree:     d.tree,
		commit:   newRef.Hash(),
	}, nil
}

func (r *gitRepository) commitPackageToMain(ctx context.Context, d *gitPackageDraft) (commitHash, newPackageTreeHash plumbing.Hash, base *plumbing.Reference, err error) {
	branch := r.branch
	localRef := branch.RefInLocal()

	var zero plumbing.Hash
	auth, err := r.getAuthMethod(ctx)

	if err != nil {
		return zero, zero, nil, fmt.Errorf("failed to obtain git credentials: %w", err)
	}

	repo := r.repo

	// Fetch main
	switch err := repo.Fetch(&git.FetchOptions{
		RemoteName: OriginName,
		RefSpecs:   []config.RefSpec{branch.ForceFetchSpec()},
		Auth:       auth,
	}); err {
	case nil, git.NoErrAlreadyUpToDate:
		// ok
	default:
		return zero, zero, nil, fmt.Errorf("failed to fetch remote repository: %w", err)
	}

	// Find localTarget branch
	localTarget, err := repo.Reference(localRef, false)
	if err != nil {
		// TODO: handle empty repositories - NotFound error
		return zero, zero, nil, fmt.Errorf("failed to find 'main' branch: %w", err)
	}
	headCommit, err := repo.CommitObject(localTarget.Hash())
	if err != nil {
		return zero, zero, nil, fmt.Errorf("failed to resolve main branch to commit: %w", err)
	}
	headRoot, err := headCommit.Tree()
	if err != nil {
		// TODO: handle empty repositories
		return zero, zero, nil, fmt.Errorf("failed to get main commit tree; %w", err)
	}
	packagePath := d.path
	packageTree := d.tree
	if packageEntry, err := headRoot.FindEntry(packagePath); err == nil {
		if packageEntry.Hash != packageTree {
			return zero, zero, nil, fmt.Errorf("internal error: package tree consistency check failed: %s != %s", packageEntry.Hash, packageTree)
		}
	}

	// TODO: Check for out-of-band update of the package in main branch
	// (compare package tree in target branch and common base)
	ch, err := newCommitHelper(repo.Storer, r.userInfoProvider, headCommit.Hash, packagePath, packageTree)
	if err != nil {
		return zero, zero, nil, fmt.Errorf("failed to initialize commit of package %s to %s", packagePath, localRef)
	}
	message := fmt.Sprintf("Approve %s", packagePath)
	commitHash, newPackageTreeHash, err = ch.commit(ctx, message, packagePath)
	if err != nil {
		return zero, zero, nil, fmt.Errorf("failed to commit package %s to %s", packagePath, localRef)
	}

	return commitHash, newPackageTreeHash, localTarget, nil
}
<commit_msg>Remove Erroneous Consistency Check (#2981)<commit_after>// Copyright 2022 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 git

import (
	"context"
	"fmt"
	"path"
	"time"

	"github.com/GoogleContainerTools/kpt/porch/api/porch/v1alpha1"
	"github.com/GoogleContainerTools/kpt/porch/repository/pkg/repository"
	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/config"
	"github.com/go-git/go-git/v5/plumbing"
)

type gitPackageDraft struct {
	parent    *gitRepository
	path      string
	revision  string
	lifecycle v1alpha1.PackageRevisionLifecycle // New value of the package revision lifecycle
	updated   time.Time
	base      *plumbing.Reference // ref to the base of the package update commit chain (used for conditional push)
	branch    BranchName          // name of the branch where the changes will be pushed
	commit    plumbing.Hash       // Current HEAD of the package changes (commit sha)
	tree      plumbing.Hash       // Cached tree of the package itself, some descendent of commit.Tree()
}

var _ repository.PackageDraft = &gitPackageDraft{}

func (d *gitPackageDraft) UpdateResources(ctx context.Context, new *v1alpha1.PackageRevisionResources, change *v1alpha1.Task) error {
	ch, err := newCommitHelper(d.parent.repo.Storer, d.parent.userInfoProvider, d.commit, d.path, plumbing.ZeroHash)
	if err != nil {
		return fmt.Errorf("failed to commit packgae: %w", err)
	}

	for k, v := range new.Spec.Resources {
		ch.storeFile(path.Join(d.path, k), v)
	}

	message := fmt.Sprintf("Intermittent commit: %s", change.Type)
	commitHash, packageTree, err := ch.commit(ctx, message, d.path)
	if err != nil {
		return fmt.Errorf("failed to commit package: %w", err)
	}

	d.tree = packageTree
	d.commit = commitHash
	return nil
}

func (d *gitPackageDraft) UpdateLifecycle(ctx context.Context, new v1alpha1.PackageRevisionLifecycle) error {
	d.lifecycle = new
	return nil
}

// Finish round of updates.
func (d *gitPackageDraft) Close(ctx context.Context) (repository.PackageRevision, error) {
	return d.parent.closeDraft(ctx, d)
}

func (r *gitRepository) closeDraft(ctx context.Context, d *gitPackageDraft) (*gitPackageRevision, error) {
	refSpecs := newPushRefSpecBuilder()
	draftBranch := createDraftName(d.path, d.revision)
	proposedBranch := createProposedName(d.path, d.revision)

	var newRef *plumbing.Reference

	switch d.lifecycle {
	case v1alpha1.PackageRevisionLifecycleFinal:
		// Finalize the package revision. Commit it to main branch.
		commitHash, newTreeHash, commitBase, err := r.commitPackageToMain(ctx, d)
		if err != nil {
			return nil, err
		}

		tag := createFinalTagNameInLocal(d.path, d.revision)
		refSpecs.AddRefToPush(commitHash, r.branch.RefInLocal()) // Push new main branch
		refSpecs.AddRefToPush(commitHash, tag)                   // Push the tag
		refSpecs.RequireRef(commitBase)                          // Make sure main didn't advance

		// Delete base branch (if one exists and should be deleted)
		switch base := d.base; {
		case base == nil: // no branch to delete
		case base.Name() == draftBranch.RefInLocal(), base.Name() == proposedBranch.RefInLocal():
			refSpecs.AddRefToDelete(base)
		}

		// Update package draft
		d.commit = commitHash
		d.tree = newTreeHash
		newRef = plumbing.NewHashReference(tag, commitHash)

	case v1alpha1.PackageRevisionLifecycleProposed:
		// Push the package revision into a proposed branch.
		refSpecs.AddRefToPush(d.commit, proposedBranch.RefInLocal())

		// Delete base branch (if one exists and should be deleted)
		switch base := d.base; {
		case base == nil: // no branch to delete
		case base.Name() != proposedBranch.RefInLocal():
			refSpecs.AddRefToDelete(base)
		}

		// Update package referemce (commit and tree hash stay the same)
		newRef = plumbing.NewHashReference(proposedBranch.RefInLocal(), d.commit)

	case v1alpha1.PackageRevisionLifecycleDraft:
		// Push the package revision into a draft branch.
		refSpecs.AddRefToPush(d.commit, draftBranch.RefInLocal())
		// Delete base branch (if one exists and should be deleted)
		switch base := d.base; {
		case base == nil: // no branch to delete
		case base.Name() != draftBranch.RefInLocal():
			refSpecs.AddRefToDelete(base)
		}

		// Update package referemce (commit and tree hash stay the same)
		newRef = plumbing.NewHashReference(draftBranch.RefInLocal(), d.commit)

	default:
		return nil, fmt.Errorf("package has unrecognized lifecycle: %q", d.lifecycle)
	}

	if err := d.parent.pushAndCleanup(ctx, refSpecs); err != nil {
		return nil, err
	}

	return &gitPackageRevision{
		parent:   d.parent,
		path:     d.path,
		revision: d.revision,
		updated:  d.updated,
		ref:      newRef,
		tree:     d.tree,
		commit:   newRef.Hash(),
	}, nil
}

func (r *gitRepository) commitPackageToMain(ctx context.Context, d *gitPackageDraft) (commitHash, newPackageTreeHash plumbing.Hash, base *plumbing.Reference, err error) {
	branch := r.branch
	localRef := branch.RefInLocal()

	var zero plumbing.Hash
	auth, err := r.getAuthMethod(ctx)

	if err != nil {
		return zero, zero, nil, fmt.Errorf("failed to obtain git credentials: %w", err)
	}

	repo := r.repo

	// Fetch main
	switch err := repo.Fetch(&git.FetchOptions{
		RemoteName: OriginName,
		RefSpecs:   []config.RefSpec{branch.ForceFetchSpec()},
		Auth:       auth,
	}); err {
	case nil, git.NoErrAlreadyUpToDate:
		// ok
	default:
		return zero, zero, nil, fmt.Errorf("failed to fetch remote repository: %w", err)
	}

	// Find localTarget branch
	localTarget, err := repo.Reference(localRef, false)
	if err != nil {
		// TODO: handle empty repositories - NotFound error
		return zero, zero, nil, fmt.Errorf("failed to find 'main' branch: %w", err)
	}
	headCommit, err := repo.CommitObject(localTarget.Hash())
	if err != nil {
		return zero, zero, nil, fmt.Errorf("failed to resolve main branch to commit: %w", err)
	}
	packagePath := d.path
	packageTree := d.tree

	// TODO: Check for out-of-band update of the package in main branch
	// (compare package tree in target branch and common base)
	ch, err := newCommitHelper(repo.Storer, r.userInfoProvider, headCommit.Hash, packagePath, packageTree)
	if err != nil {
		return zero, zero, nil, fmt.Errorf("failed to initialize commit of package %s to %s", packagePath, localRef)
	}
	message := fmt.Sprintf("Approve %s", packagePath)
	commitHash, newPackageTreeHash, err = ch.commit(ctx, message, packagePath)
	if err != nil {
		return zero, zero, nil, fmt.Errorf("failed to commit package %s to %s", packagePath, localRef)
	}

	return commitHash, newPackageTreeHash, localTarget, nil
}
<|endoftext|>


<commit_before>package porterstemmer

import (
	"bufio"
	"os"
	"strings"
    "testing"
)

func TestStemString(t *testing.T) {

	vocFileName := "testdata/voc.txt"
	vocFd, err := os.Open(vocFileName)
	if nil != err {
		t.Errorf("Could NOT open testdata file: [%s]. Received error: [%v]", vocFileName, err)
/////// RETURN
		return
	}
	defer vocFd.Close()

	voc := bufio.NewReaderSize(vocFd, 1024)

	outFileName := "testdata/output.txt"
	outFd, err := os.Open(outFileName)
	if nil != err {
		t.Errorf("Could NOT open testdata file: [%s]. Received error: [%v]", outFileName, err)
/////// RETURN
		return
	}
	defer outFd.Close()

	out := bufio.NewReaderSize(outFd, 1024)

	for {

		vocS, err := voc.ReadString('\n')
		if nil != err {
	/////// BREAK
			break
		}

		vocS = strings.Trim(vocS, "\n\r\t ")

		expected, err := out.ReadString('\n')
		if nil != err {
			t.Errorf("Received unexpected error when trying to read a line from [%s]. Received error: [%v]", outFileName, err)
	/////// BREAK
			break

		}

		expected = strings.Trim(expected, "\n\r\t ")

		actual := StemString(vocS)
		if expected != actual {
			t.Errorf("Input: [%s] -> Actual: [%s]. Expected: [%s]", vocS, actual, expected)
		}
	}
}
<commit_msg>made it so this test can download the test files it needs<commit_after>package porterstemmer

import (
	"bufio"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
    "testing"
)

func TestStemString(t *testing.T) {

	testDataDirName := "testdata"

	_, err := os.Stat(testDataDirName)
	if nil != err {
		_ = os.Mkdir(testDataDirName, 0755)
	}
	_, err = os.Stat(testDataDirName)
	if nil != err {
		t.Errorf("The test data folder ([%s]) does not exists (and could not create it). Received error: [%v]", testDataDirName, err)
/////// RETURN
		return
	}

	vocFileName := testDataDirName + "/voc.txt"
	_, err = os.Stat(vocFileName)
	if nil != err {

		vocHref := "http://tartarus.org/martin/PorterStemmer/voc.txt"

		resp, err := http.Get(vocHref)
		if nil != err {
			t.Errorf("Could not download test file (from web) from URL: [%s]. Received error: [%v]", vocHref, err)
/////////// RETURN
			return
		}

		respBody, err := ioutil.ReadAll(resp.Body)
		if nil != err {
			t.Errorf("Error loading the contents of from URL: [%s]. Received error: [%v].", vocHref, err)
/////////// RETURN
			return
		}

		_ = ioutil.WriteFile(vocFileName, respBody, 0644)

	}
	vocFd, err := os.Open(vocFileName)
	if nil != err {
		t.Errorf("Could NOT open testdata file: [%s]. Received error: [%v]", vocFileName, err)
/////// RETURN
		return
	}
	defer vocFd.Close()

	voc := bufio.NewReaderSize(vocFd, 1024)

	outFileName := testDataDirName + "/output.txt"
	_, err = os.Stat(outFileName)
	if nil != err {

		outHref := "http://tartarus.org/martin/PorterStemmer/output.txt"

		resp, err := http.Get(outHref)
		if nil != err {
			t.Errorf("Could not download test file (from web) from URL: [%s]. Received error: [%v]", outHref, err)
/////////// RETURN
			return
		}

		respBody, err := ioutil.ReadAll(resp.Body)
		if nil != err {
			t.Errorf("Error loading the contents of from URL: [%s]. Received error: [%v].", outHref, err)
/////////// RETURN
			return
		}

		_ = ioutil.WriteFile(outFileName, respBody, 0644)

	}
	outFd, err := os.Open(outFileName)
	if nil != err {
		t.Errorf("Could NOT open testdata file: [%s]. Received error: [%v]", outFileName, err)
/////// RETURN
		return
	}
	defer outFd.Close()

	out := bufio.NewReaderSize(outFd, 1024)

	for {

		vocS, err := voc.ReadString('\n')
		if nil != err {
	/////// BREAK
			break
		}

		vocS = strings.Trim(vocS, "\n\r\t ")

		expected, err := out.ReadString('\n')
		if nil != err {
			t.Errorf("Received unexpected error when trying to read a line from [%s]. Received error: [%v]", outFileName, err)
	/////// BREAK
			break

		}

		expected = strings.Trim(expected, "\n\r\t ")

		actual := StemString(vocS)
		if expected != actual {
			t.Errorf("Input: [%s] -> Actual: [%s]. Expected: [%s]", vocS, actual, expected)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"math/rand"
	"net/url"
	"strconv"
	"sync"
	"time"

	"qbox.us/cc/config"

	"github.com/influxdb/influxdb/client"

	qlog "github.com/qiniu/log.v1"
)

type Config struct {
	URL                     string            `json:"influxURL"`
	Database                string            `json:"database"`
	Retention               string            `json:"retention"`
	Precision               string            `json:"precision"`
	GorutineNum             int               `json:"gorutineNum"`
	BatchSize               int               `json:"batchSize"`
	BatchPointsInSameSeries bool              `json:"batchPointsInSameSeries"`
	BatchCountPerSecond     int               `json:"batchCountPerSecond"`
	DebugLevel              int               `json:"debugLevel"`
	Measurement             string            `json:"measurement`
	TagKeySet               []string          `json:"tagKeySet"`
	FieldKeySet             []string          `json:"fieldKeySet"`
	FieldValueRange         []FieldValueRange `json:"fieldValueRange"`
}

type FieldValueRange struct {
	Type  string `json:"type"`
	Start string `json:"start"`
	End   string `json:"end"`
}

func main() {

	config.Init("f", "", "benchmark.conf")

	var wg sync.WaitGroup
	var conf Config
	if err := config.Load(&conf); err != nil {
		qlog.Fatal("config.Load failed:", err)
		return
	}

	qlog.SetOutputLevel(conf.DebugLevel)

	host, err := url.Parse(conf.URL)

	if err != nil {
		return
	}

	var gorutineClients []*client.Client
	gorutineClients = make([]*client.Client, conf.GorutineNum)

	qlog.Debugf("The gorutineNum is %d", conf.GorutineNum)

	for i := 0; i < conf.GorutineNum; i++ {

		gorutineClients[i], err = client.NewClient(client.Config{URL: *host})
		if err != nil {
			return
		}

		wg.Add(1)
		go writePoints(i, gorutineClients[i], &conf)
	}
	wg.Wait()
}

func writePoints(num int, gorutineClient *client.Client, conf *Config) {

	batchCount := 1000 / conf.BatchCountPerSecond
	writeTimeDuration := (time.Duration(batchCount)) * time.Millisecond

	writeTimer := time.NewTimer(writeTimeDuration)

	batchSize := conf.BatchSize

	batchPointsInSameSeries := conf.BatchPointsInSameSeries

	tagKeySet := conf.TagKeySet
	fieldKeySet := conf.FieldKeySet

	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	for {
		<-writeTimer.C

		pts := make([]client.Point, batchSize)

		for i := 0; i < batchSize; i++ {

			tagSet := make(map[string]string, len(tagKeySet))
			fieldSet := make(map[string]interface{}, len(fieldKeySet))

			for _, tag := range tagKeySet {
				tagSet[tag] = tag + "_" + strconv.Itoa(num)
			}

			if !batchPointsInSameSeries {
				for _, tag := range tagKeySet {
					tagSet[tag] = tag + strconv.Itoa(i)
				}
			}

			for index, val := range fieldKeySet {

				valueContent := conf.FieldValueRange[index]

				if valueContent.Type == "float" {
					start, _ := strconv.ParseFloat(conf.FieldValueRange[index].Start, 32)
					end, _ := strconv.ParseFloat(conf.FieldValueRange[index].End, 32)
					v := start + r.Float64()*(end-start)
					fieldSet[val] = v
				}

				if conf.FieldValueRange[index].Type == "integer" {
					start, _ := strconv.Atoi(conf.FieldValueRange[index].Start)
					end, _ := strconv.Atoi(conf.FieldValueRange[index].End)
					v := start + r.Intn(end-start)
					fieldSet[val] = v
				}

				if conf.FieldValueRange[index].Type == "string" {
				}

				if conf.FieldValueRange[index].Type == "bool" {
				}
			}

			pts[i] = client.Point{
				Measurement: conf.Measurement,
				Tags:        tagSet,
				Fields:      fieldSet,
				Time:        time.Now(),
				Precision:   conf.Precision,
			}
		}

		bp := client.BatchPoints{
			Points:          pts,
			Database:        conf.Database,
			RetentionPolicy: conf.Retention,
		}

		qlog.Debugf("gorutine number is %d, Write %d points", num, len(bp.Points))

		_, err := gorutineClient.Write(bp)

		if err != nil {
			qlog.Debug(err)
			return
		}

		writeTimer.Reset(writeTimeDuration)
	}

}
<commit_msg>Add repoId tag<commit_after>package main

import (
	"math/rand"
	"net/url"
	"strconv"
	"sync"
	"time"

	"qbox.us/cc/config"

	"github.com/influxdb/influxdb/client"

	qlog "github.com/qiniu/log.v1"
)

type Config struct {
	URL                     string            `json:"influxURL"`
	RepoId                  string            `json:"repoId"`
	Database                string            `json:"database"`
	Retention               string            `json:"retention"`
	Precision               string            `json:"precision"`
	GorutineNum             int               `json:"gorutineNum"`
	BatchSize               int               `json:"batchSize"`
	BatchPointsInSameSeries bool              `json:"batchPointsInSameSeries"`
	BatchCountPerSecond     int               `json:"batchCountPerSecond"`
	DebugLevel              int               `json:"debugLevel"`
	Measurement             string            `json:"measurement`
	TagKeySet               []string          `json:"tagKeySet"`
	FieldKeySet             []string          `json:"fieldKeySet"`
	FieldValueRange         []FieldValueRange `json:"fieldValueRange"`
}

type FieldValueRange struct {
	Type  string `json:"type"`
	Start string `json:"start"`
	End   string `json:"end"`
}

func main() {

	config.Init("f", "", "benchmark.conf")

	var wg sync.WaitGroup
	var conf Config
	if err := config.Load(&conf); err != nil {
		qlog.Fatal("config.Load failed:", err)
		return
	}

	qlog.SetOutputLevel(conf.DebugLevel)

	host, err := url.Parse(conf.URL)

	if err != nil {
		return
	}

	var gorutineClients []*client.Client
	gorutineClients = make([]*client.Client, conf.GorutineNum)

	qlog.Debugf("The gorutineNum is %d", conf.GorutineNum)

	for i := 0; i < conf.GorutineNum; i++ {

		gorutineClients[i], err = client.NewClient(client.Config{URL: *host})
		if err != nil {
			return
		}

		wg.Add(1)
		go writePoints(i, gorutineClients[i], &conf)
	}
	wg.Wait()
}

func writePoints(num int, gorutineClient *client.Client, conf *Config) {

	batchCount := 1000 / conf.BatchCountPerSecond
	writeTimeDuration := (time.Duration(batchCount)) * time.Millisecond

	writeTimer := time.NewTimer(writeTimeDuration)

	batchSize := conf.BatchSize

	batchPointsInSameSeries := conf.BatchPointsInSameSeries

	tagKeySet := conf.TagKeySet
	fieldKeySet := conf.FieldKeySet

	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	for {
		<-writeTimer.C

		pts := make([]client.Point, batchSize)

		for i := 0; i < batchSize; i++ {

			// tagSet := make(map[string]string, len(tagKeySet))
			tagSet := make(map[string]string, len(tagKeySet+1))
			fieldSet := make(map[string]interface{}, len(fieldKeySet))

			for _, tag := range tagKeySet {
				tagSet[tag] = tag + "_" + strconv.Itoa(num)
			}

			if !batchPointsInSameSeries {
				for _, tag := range tagKeySet {
					tagSet[tag] = tag + strconv.Itoa(i)
				}
			}

			for index, val := range fieldKeySet {

				valueContent := conf.FieldValueRange[index]

				if valueContent.Type == "float" {
					start, _ := strconv.ParseFloat(conf.FieldValueRange[index].Start, 32)
					end, _ := strconv.ParseFloat(conf.FieldValueRange[index].End, 32)
					v := start + r.Float64()*(end-start)
					fieldSet[val] = v
				}

				if conf.FieldValueRange[index].Type == "integer" {
					start, _ := strconv.Atoi(conf.FieldValueRange[index].Start)
					end, _ := strconv.Atoi(conf.FieldValueRange[index].End)
					v := start + r.Intn(end-start)
					fieldSet[val] = v
				}

				if conf.FieldValueRange[index].Type == "string" {
				}

				if conf.FieldValueRange[index].Type == "bool" {
				}
			}

			tagSet["repoid"] = conf.RepoId

			pts[i] = client.Point{
				Measurement: conf.Measurement,
				Tags:        tagSet,
				Fields:      fieldSet,
				Time:        time.Now(),
				Precision:   conf.Precision,
			}
		}

		bp := client.BatchPoints{
			Points:          pts,
			Database:        conf.Database,
			RetentionPolicy: conf.Retention,
		}

		qlog.Debugf("gorutine number is %d, Write %d points", num, len(bp.Points))

		_, err := gorutineClient.Write(bp)

		if err != nil {
			qlog.Debug(err)
			return
		}

		writeTimer.Reset(writeTimeDuration)
	}

}
<|endoftext|>


<commit_before>package kubernetes

import (
	"fmt"
	"regexp"
	"strings"
	"time"

	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/pkg/apis/extensions/v1beta1"

	"github.com/rusenask/keel/extension/notification"
	"github.com/rusenask/keel/types"
	"github.com/rusenask/keel/util/image"
	"github.com/rusenask/keel/util/policies"
	"github.com/rusenask/keel/util/version"

	log "github.com/Sirupsen/logrus"
)

// ProviderName - provider name
const ProviderName = "kubernetes"

var versionreg = regexp.MustCompile(`:[^:]*$`)

// annotation used to specify which image to force pull
const forceUpdateImageAnnotation = "keel.sh/update-image"

// forceUpdateResetTag - tag used to reset container to force pull image
const forceUpdateResetTag = "0.0.0"

// Provider - kubernetes provider for auto update
type Provider struct {
	implementer Implementer

	sender notification.Sender

	events chan *types.Event
	stop   chan struct{}
}

// NewProvider - create new kubernetes based provider
func NewProvider(implementer Implementer, sender notification.Sender) (*Provider, error) {
	return &Provider{
		implementer: implementer,
		events:      make(chan *types.Event, 100),
		stop:        make(chan struct{}),
		sender:      sender,
	}, nil
}

// Submit - submit event to provider
func (p *Provider) Submit(event types.Event) error {
	p.events <- &event
	return nil
}

// GetName - get provider name
func (p *Provider) GetName() string {
	return ProviderName
}

// Start - starts kubernetes provider, waits for events
func (p *Provider) Start() error {
	return p.startInternal()
}

// Stop - stops kubernetes provider
func (p *Provider) Stop() {
	close(p.stop)
}

func (p *Provider) startInternal() error {
	for {
		select {
		case event := <-p.events:
			log.WithFields(log.Fields{
				"repository": event.Repository.Name,
				"tag":        event.Repository.Tag,
				"registry":   event.Repository.Host,
			}).Info("provider.kubernetes: processing event")
			_, err := p.processEvent(event)
			if err != nil {
				log.WithFields(log.Fields{
					"error": err,
					"image": event.Repository.Name,
					"tag":   event.Repository.Tag,
				}).Error("provider.kubernetes: failed to process event")
			}
		case <-p.stop:
			log.Info("provider.kubernetes: got shutdown signal, stopping...")
			return nil
		}
	}
}

func (p *Provider) processEvent(event *types.Event) (updated []*v1beta1.Deployment, err error) {
	impacted, err := p.impactedDeployments(&event.Repository)
	if err != nil {
		return nil, err
	}

	if len(impacted) == 0 {
		log.WithFields(log.Fields{
			"image": event.Repository.Name,
			"tag":   event.Repository.Tag,
		}).Info("provider.kubernetes: no impacted deployments found for this event")
		return
	}

	return p.updateDeployments(impacted)
}

func (p *Provider) updateDeployments(deployments []v1beta1.Deployment) (updated []*v1beta1.Deployment, err error) {
	for _, deployment := range deployments {

		reset, delta, err := checkForReset(deployment, p.implementer)
		if err != nil {
			log.WithFields(log.Fields{
				"error":       err,
				"namespace":   deployment.Namespace,
				"annotations": deployment.GetAnnotations(),
				"deployment":  deployment.Name,
			}).Error("provider.kubernetes: got error while checking deployment for reset")
			continue
		}

		// need to get the new version in order to update
		if reset {
			// FIXME: giving some time for k8s to start updating as it
			// throws an error if you try to modify deployment that's currently being updated
			time.Sleep(2 * time.Second)

			current, err := p.getDeployment(deployment.Namespace, deployment.Name)
			if err != nil {
				log.WithFields(log.Fields{
					"error":       err,
					"namespace":   deployment.Namespace,
					"annotations": deployment.GetAnnotations(),
					"deployment":  deployment.Name,
				}).Error("provider.kubernetes: got error while refreshing deployment after reset")
				continue
			}
			// apply back our changes for images
			refresh, err := applyChanges(*current, delta)
			if err != nil {
				log.WithFields(log.Fields{
					"error":       err,
					"namespace":   deployment.Namespace,
					"annotations": deployment.GetAnnotations(),
					"deployment":  deployment.Name,
				}).Error("provider.kubernetes: got error while applying deployment changes after reset")
				continue
			}
			err = p.implementer.Update(&refresh)
			if err != nil {
				log.WithFields(log.Fields{
					"error":      err,
					"namespace":  deployment.Namespace,
					"deployment": deployment.Name,
				}).Error("provider.kubernetes: got error while update deployment")
				continue
			}
			// success
			continue
		}

		err = p.implementer.Update(&deployment)
		if err != nil {
			log.WithFields(log.Fields{
				"error":      err,
				"namespace":  deployment.Namespace,
				"deployment": deployment.Name,
			}).Error("provider.kubernetes: got error while update deployment")

			p.sender.Send(types.EventNotification{
				Name:      "update deployment",
				Message:   fmt.Sprintf("Deployment %s/%s update failed, error: %s", deployment.Namespace, deployment.Name, err),
				CreatedAt: time.Now(),
				Type:      types.NotificationDeploymentUpdate,
				Level:     types.LevelError,
			})

			continue
		}

		p.sender.Send(types.EventNotification{
			Name:      "update deployment",
			Message:   fmt.Sprintf("Successfully updated deployment %s/%s (%s)", deployment.Namespace, deployment.Name, strings.Join(getImages(&deployment), ", ")),
			CreatedAt: time.Now(),
			Type:      types.NotificationDeploymentUpdate,
			Level:     types.LevelSuccess,
		})

		log.WithFields(log.Fields{
			"name":      deployment.Name,
			"namespace": deployment.Namespace,
		}).Info("provider.kubernetes: deployment updated")
		updated = append(updated, &deployment)
	}

	return
}

func getImages(deployment *v1beta1.Deployment) []string {
	var images []string
	for _, c := range deployment.Spec.Template.Spec.Containers {
		images = append(images, c.Image)
	}

	return images
}

// applies required changes for deployment, looks for images with tag 0.0.0 and
// updates
func applyChanges(current v1beta1.Deployment, delta map[string]string) (v1beta1.Deployment, error) {
	for idx, c := range current.Spec.Template.Spec.Containers {
		if strings.HasSuffix(c.Image, forceUpdateResetTag) {
			desiredImage, err := getDesiredImage(delta, c.Image)
			if err != nil {
				return v1beta1.Deployment{}, err
			}
			current.Spec.Template.Spec.Containers[idx].Image = desiredImage
			log.Infof("provider.kubernetes: delta changed applied: %s", current.Spec.Template.Spec.Containers[idx].Image)
		}
	}
	return current, nil
}

func getDesiredImage(delta map[string]string, currentImage string) (string, error) {
	currentRef, err := image.Parse(currentImage)
	if err != nil {
		return "", err
	}
	for repository, tag := range delta {
		if repository == currentRef.Repository() {
			ref, err := image.Parse(repository)
			if err != nil {
				return "", err
			}

			// updating image
			if ref.Registry() == image.DefaultRegistryHostname {
				return fmt.Sprintf("%s:%s", ref.ShortName(), tag), nil
			}
			return fmt.Sprintf("%s:%s", ref.Repository(), tag), nil
		}
	}
	return "", fmt.Errorf("image %s not found in deltas", currentImage)
}

// checkForReset returns delta to apply
func checkForReset(deployment v1beta1.Deployment, implementer Implementer) (bool, map[string]string, error) {
	reset := false
	annotations := deployment.GetAnnotations()
	delta := make(map[string]string)
	for idx, c := range deployment.Spec.Template.Spec.Containers {
		if shouldPullImage(annotations, c.Image) {
			ref, err := image.Parse(c.Image)
			if err != nil {
				return false, nil, err
			}

			c = updateContainer(c, ref, forceUpdateResetTag)

			// ensuring pull policy
			c.ImagePullPolicy = v1.PullAlways
			log.WithFields(log.Fields{
				"image":      c.Image,
				"namespace":  deployment.Namespace,
				"deployment": deployment.Name,
			}).Info("provider.kubernetes: reseting image for force pull...")
			deployment.Spec.Template.Spec.Containers[idx] = c
			reset = true
			delta[ref.Repository()] = ref.Tag()
		}
	}
	if reset {
		return reset, delta, implementer.Update(&deployment)
	}
	return false, nil, nil
}

// getDeployment - helper function to get specific deployment
func (p *Provider) getDeployment(namespace, name string) (*v1beta1.Deployment, error) {
	return p.implementer.Deployment(namespace, name)
}

// gets impacted deployments by changed repository
func (p *Provider) impactedDeployments(repo *types.Repository) ([]v1beta1.Deployment, error) {

	deploymentLists, err := p.deployments()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("provider.kubernetes: failed to get deployment lists")
		return nil, err
	}

	impacted := []v1beta1.Deployment{}

	for _, deploymentList := range deploymentLists {
		for _, deployment := range deploymentList.Items {

			labels := deployment.GetLabels()

			policy := policies.GetPolicy(labels)
			if policy == types.PolicyTypeNone {
				// skip
				continue
			}

			// annotation cleanup
			annotations := deployment.GetAnnotations()
			delete(annotations, forceUpdateImageAnnotation)
			deployment.SetAnnotations(annotations)

			newVersion, err := version.GetVersion(repo.Tag)
			if err != nil {
				// failed to get new version tag
				if policy == types.PolicyTypeForce {
					updated, shouldUpdateDeployment, err := p.checkUnversionedDeployment(policy, repo, deployment)
					if err != nil {
						log.WithFields(log.Fields{
							"error":      err,
							"deployment": deployment.Name,
							"namespace":  deployment.Namespace,
						}).Error("provider.kubernetes: got error while checking unversioned deployment")
						continue
					}

					if shouldUpdateDeployment {
						impacted = append(impacted, updated)
					}

					// success, unversioned deployment marked for update
					continue
				}

				log.WithFields(log.Fields{
					"error":          err,
					"repository_tag": repo.Tag,
					"deployment":     deployment.Name,
					"namespace":      deployment.Namespace,
					"policy":         policy,
				}).Warn("provider.kubernetes: got error while parsing repository tag")
				continue
			}

			updated, shouldUpdateDeployment, err := p.checkVersionedDeployment(newVersion, policy, repo, deployment)
			if err != nil {
				log.WithFields(log.Fields{
					"error":      err,
					"deployment": deployment.Name,
					"namespace":  deployment.Namespace,
				}).Error("provider.kubernetes: got error while checking versioned deployment")
				continue
			}

			if shouldUpdateDeployment {
				impacted = append(impacted, updated)
			}
		}
	}

	return impacted, nil
}

func (p *Provider) namespaces() (*v1.NamespaceList, error) {
	return p.implementer.Namespaces()
}

// deployments - gets all deployments
func (p *Provider) deployments() ([]*v1beta1.DeploymentList, error) {
	deployments := []*v1beta1.DeploymentList{}

	n, err := p.namespaces()
	if err != nil {
		return nil, err
	}

	for _, n := range n.Items {
		l, err := p.implementer.Deployments(n.GetName())
		if err != nil {
			log.WithFields(log.Fields{
				"error":     err,
				"namespace": n.GetName(),
			}).Error("provider.kubernetes: failed to list deployments")
			continue
		}
		deployments = append(deployments, l)
	}

	return deployments, nil
}
<commit_msg>sending debug notification prior to deployment<commit_after>package kubernetes

import (
	"fmt"
	"regexp"
	"strings"
	"time"

	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/pkg/apis/extensions/v1beta1"

	"github.com/rusenask/keel/extension/notification"
	"github.com/rusenask/keel/types"
	"github.com/rusenask/keel/util/image"
	"github.com/rusenask/keel/util/policies"
	"github.com/rusenask/keel/util/version"

	log "github.com/Sirupsen/logrus"
)

// ProviderName - provider name
const ProviderName = "kubernetes"

var versionreg = regexp.MustCompile(`:[^:]*$`)

// annotation used to specify which image to force pull
const forceUpdateImageAnnotation = "keel.sh/update-image"

// forceUpdateResetTag - tag used to reset container to force pull image
const forceUpdateResetTag = "0.0.0"

// Provider - kubernetes provider for auto update
type Provider struct {
	implementer Implementer

	sender notification.Sender

	events chan *types.Event
	stop   chan struct{}
}

// NewProvider - create new kubernetes based provider
func NewProvider(implementer Implementer, sender notification.Sender) (*Provider, error) {
	return &Provider{
		implementer: implementer,
		events:      make(chan *types.Event, 100),
		stop:        make(chan struct{}),
		sender:      sender,
	}, nil
}

// Submit - submit event to provider
func (p *Provider) Submit(event types.Event) error {
	p.events <- &event
	return nil
}

// GetName - get provider name
func (p *Provider) GetName() string {
	return ProviderName
}

// Start - starts kubernetes provider, waits for events
func (p *Provider) Start() error {
	return p.startInternal()
}

// Stop - stops kubernetes provider
func (p *Provider) Stop() {
	close(p.stop)
}

func (p *Provider) startInternal() error {
	for {
		select {
		case event := <-p.events:
			log.WithFields(log.Fields{
				"repository": event.Repository.Name,
				"tag":        event.Repository.Tag,
				"registry":   event.Repository.Host,
			}).Info("provider.kubernetes: processing event")
			_, err := p.processEvent(event)
			if err != nil {
				log.WithFields(log.Fields{
					"error": err,
					"image": event.Repository.Name,
					"tag":   event.Repository.Tag,
				}).Error("provider.kubernetes: failed to process event")
			}
		case <-p.stop:
			log.Info("provider.kubernetes: got shutdown signal, stopping...")
			return nil
		}
	}
}

func (p *Provider) processEvent(event *types.Event) (updated []*v1beta1.Deployment, err error) {
	impacted, err := p.impactedDeployments(&event.Repository)
	if err != nil {
		return nil, err
	}

	if len(impacted) == 0 {
		log.WithFields(log.Fields{
			"image": event.Repository.Name,
			"tag":   event.Repository.Tag,
		}).Info("provider.kubernetes: no impacted deployments found for this event")
		return
	}

	return p.updateDeployments(impacted)
}

func (p *Provider) updateDeployments(deployments []v1beta1.Deployment) (updated []*v1beta1.Deployment, err error) {
	for _, deployment := range deployments {

		reset, delta, err := checkForReset(deployment, p.implementer)
		if err != nil {
			log.WithFields(log.Fields{
				"error":       err,
				"namespace":   deployment.Namespace,
				"annotations": deployment.GetAnnotations(),
				"deployment":  deployment.Name,
			}).Error("provider.kubernetes: got error while checking deployment for reset")
			continue
		}

		// need to get the new version in order to update
		if reset {
			// FIXME: giving some time for k8s to start updating as it
			// throws an error if you try to modify deployment that's currently being updated
			time.Sleep(2 * time.Second)

			current, err := p.getDeployment(deployment.Namespace, deployment.Name)
			if err != nil {
				log.WithFields(log.Fields{
					"error":       err,
					"namespace":   deployment.Namespace,
					"annotations": deployment.GetAnnotations(),
					"deployment":  deployment.Name,
				}).Error("provider.kubernetes: got error while refreshing deployment after reset")
				continue
			}
			// apply back our changes for images
			refresh, err := applyChanges(*current, delta)
			if err != nil {
				log.WithFields(log.Fields{
					"error":       err,
					"namespace":   deployment.Namespace,
					"annotations": deployment.GetAnnotations(),
					"deployment":  deployment.Name,
				}).Error("provider.kubernetes: got error while applying deployment changes after reset")
				continue
			}
			err = p.implementer.Update(&refresh)
			if err != nil {
				log.WithFields(log.Fields{
					"error":      err,
					"namespace":  deployment.Namespace,
					"deployment": deployment.Name,
				}).Error("provider.kubernetes: got error while update deployment")
				continue
			}
			// success
			continue
		}

		p.sender.Send(types.EventNotification{
			Name:      "preparing to update deployment",
			Message:   fmt.Sprintf("Preparing to update deployment %s/%s (%s)", deployment.Namespace, deployment.Name, strings.Join(getImages(&deployment), ", ")),
			CreatedAt: time.Now(),
			Type:      types.NotificationPreDeploymentUpdate,
			Level:     types.LevelDebug,
		})

		err = p.implementer.Update(&deployment)
		if err != nil {
			log.WithFields(log.Fields{
				"error":      err,
				"namespace":  deployment.Namespace,
				"deployment": deployment.Name,
			}).Error("provider.kubernetes: got error while update deployment")

			p.sender.Send(types.EventNotification{
				Name:      "update deployment",
				Message:   fmt.Sprintf("Deployment %s/%s update failed, error: %s", deployment.Namespace, deployment.Name, err),
				CreatedAt: time.Now(),
				Type:      types.NotificationDeploymentUpdate,
				Level:     types.LevelError,
			})

			continue
		}

		p.sender.Send(types.EventNotification{
			Name:      "update deployment",
			Message:   fmt.Sprintf("Successfully updated deployment %s/%s (%s)", deployment.Namespace, deployment.Name, strings.Join(getImages(&deployment), ", ")),
			CreatedAt: time.Now(),
			Type:      types.NotificationDeploymentUpdate,
			Level:     types.LevelSuccess,
		})

		log.WithFields(log.Fields{
			"name":      deployment.Name,
			"namespace": deployment.Namespace,
		}).Info("provider.kubernetes: deployment updated")
		updated = append(updated, &deployment)
	}

	return
}

func getImages(deployment *v1beta1.Deployment) []string {
	var images []string
	for _, c := range deployment.Spec.Template.Spec.Containers {
		images = append(images, c.Image)
	}

	return images
}

// applies required changes for deployment, looks for images with tag 0.0.0 and
// updates
func applyChanges(current v1beta1.Deployment, delta map[string]string) (v1beta1.Deployment, error) {
	for idx, c := range current.Spec.Template.Spec.Containers {
		if strings.HasSuffix(c.Image, forceUpdateResetTag) {
			desiredImage, err := getDesiredImage(delta, c.Image)
			if err != nil {
				return v1beta1.Deployment{}, err
			}
			current.Spec.Template.Spec.Containers[idx].Image = desiredImage
			log.Infof("provider.kubernetes: delta changed applied: %s", current.Spec.Template.Spec.Containers[idx].Image)
		}
	}
	return current, nil
}

func getDesiredImage(delta map[string]string, currentImage string) (string, error) {
	currentRef, err := image.Parse(currentImage)
	if err != nil {
		return "", err
	}
	for repository, tag := range delta {
		if repository == currentRef.Repository() {
			ref, err := image.Parse(repository)
			if err != nil {
				return "", err
			}

			// updating image
			if ref.Registry() == image.DefaultRegistryHostname {
				return fmt.Sprintf("%s:%s", ref.ShortName(), tag), nil
			}
			return fmt.Sprintf("%s:%s", ref.Repository(), tag), nil
		}
	}
	return "", fmt.Errorf("image %s not found in deltas", currentImage)
}

// checkForReset returns delta to apply
func checkForReset(deployment v1beta1.Deployment, implementer Implementer) (bool, map[string]string, error) {
	reset := false
	annotations := deployment.GetAnnotations()
	delta := make(map[string]string)
	for idx, c := range deployment.Spec.Template.Spec.Containers {
		if shouldPullImage(annotations, c.Image) {
			ref, err := image.Parse(c.Image)
			if err != nil {
				return false, nil, err
			}

			c = updateContainer(c, ref, forceUpdateResetTag)

			// ensuring pull policy
			c.ImagePullPolicy = v1.PullAlways
			log.WithFields(log.Fields{
				"image":      c.Image,
				"namespace":  deployment.Namespace,
				"deployment": deployment.Name,
			}).Info("provider.kubernetes: reseting image for force pull...")
			deployment.Spec.Template.Spec.Containers[idx] = c
			reset = true
			delta[ref.Repository()] = ref.Tag()
		}
	}
	if reset {
		return reset, delta, implementer.Update(&deployment)
	}
	return false, nil, nil
}

// getDeployment - helper function to get specific deployment
func (p *Provider) getDeployment(namespace, name string) (*v1beta1.Deployment, error) {
	return p.implementer.Deployment(namespace, name)
}

// gets impacted deployments by changed repository
func (p *Provider) impactedDeployments(repo *types.Repository) ([]v1beta1.Deployment, error) {

	deploymentLists, err := p.deployments()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("provider.kubernetes: failed to get deployment lists")
		return nil, err
	}

	impacted := []v1beta1.Deployment{}

	for _, deploymentList := range deploymentLists {
		for _, deployment := range deploymentList.Items {

			labels := deployment.GetLabels()

			policy := policies.GetPolicy(labels)
			if policy == types.PolicyTypeNone {
				// skip
				continue
			}

			// annotation cleanup
			annotations := deployment.GetAnnotations()
			delete(annotations, forceUpdateImageAnnotation)
			deployment.SetAnnotations(annotations)

			newVersion, err := version.GetVersion(repo.Tag)
			if err != nil {
				// failed to get new version tag
				if policy == types.PolicyTypeForce {
					updated, shouldUpdateDeployment, err := p.checkUnversionedDeployment(policy, repo, deployment)
					if err != nil {
						log.WithFields(log.Fields{
							"error":      err,
							"deployment": deployment.Name,
							"namespace":  deployment.Namespace,
						}).Error("provider.kubernetes: got error while checking unversioned deployment")
						continue
					}

					if shouldUpdateDeployment {
						impacted = append(impacted, updated)
					}

					// success, unversioned deployment marked for update
					continue
				}

				log.WithFields(log.Fields{
					"error":          err,
					"repository_tag": repo.Tag,
					"deployment":     deployment.Name,
					"namespace":      deployment.Namespace,
					"policy":         policy,
				}).Warn("provider.kubernetes: got error while parsing repository tag")
				continue
			}

			updated, shouldUpdateDeployment, err := p.checkVersionedDeployment(newVersion, policy, repo, deployment)
			if err != nil {
				log.WithFields(log.Fields{
					"error":      err,
					"deployment": deployment.Name,
					"namespace":  deployment.Namespace,
				}).Error("provider.kubernetes: got error while checking versioned deployment")
				continue
			}

			if shouldUpdateDeployment {
				impacted = append(impacted, updated)
			}
		}
	}

	return impacted, nil
}

func (p *Provider) namespaces() (*v1.NamespaceList, error) {
	return p.implementer.Namespaces()
}

// deployments - gets all deployments
func (p *Provider) deployments() ([]*v1beta1.DeploymentList, error) {
	deployments := []*v1beta1.DeploymentList{}

	n, err := p.namespaces()
	if err != nil {
		return nil, err
	}

	for _, n := range n.Items {
		l, err := p.implementer.Deployments(n.GetName())
		if err != nil {
			log.WithFields(log.Fields{
				"error":     err,
				"namespace": n.GetName(),
			}).Error("provider.kubernetes: failed to list deployments")
			continue
		}
		deployments = append(deployments, l)
	}

	return deployments, nil
}
<|endoftext|>


<commit_before>// Copyright 2019 The Terraformer 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 azure

import (
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/Azure/go-autorest/autorest"
	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
	"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
	"github.com/hashicorp/go-azure-helpers/authentication"
	"github.com/hashicorp/go-azure-helpers/sender"
)

type AzureProvider struct { //nolint
	terraformutils.Provider
	config     authentication.Config
	authorizer autorest.Authorizer
}

func (p *AzureProvider) setEnvConfig() error {
	subscriptionID := os.Getenv("ARM_SUBSCRIPTION_ID")
	if subscriptionID == "" {
		return errors.New("set ARM_SUBSCRIPTION_ID env var")
	}
	builder := &authentication.Builder{
		ClientID:                 os.Getenv("ARM_CLIENT_ID"),
		SubscriptionID:           subscriptionID,
		TenantID:                 os.Getenv("ARM_TENANT_ID"),
		Environment:              os.Getenv("ARM_ENVIRONMENT"),
		ClientSecret:             os.Getenv("ARM_CLIENT_SECRET"),
		SupportsAzureCliToken:    true,
		SupportsClientSecretAuth: true,
		SupportsClientCertAuth:   true,
		ClientCertPath:           os.Getenv("ARM_CLIENT_CERTIFICATE_PATH"),
		ClientCertPassword:       os.Getenv("ARM_CLIENT_CERTIFICATE_PASSWORD"),

		/*
		   // Managed Service Identity Auth
		   SupportsManagedServiceIdentity bool
		   MsiEndpoint                    string
		*/
	}

	if builder.Environment == "" {
		builder.Environment = "public"
	}
	config, err := builder.Build()
	if err != nil {
		return nil
	}
	p.config = *config

	return nil
}

func (p *AzureProvider) getAuthorizer() (autorest.Authorizer, error) {
	env, err := authentication.DetermineEnvironment(p.config.Environment)
	if err != nil {
		return nil, err
	}

	oauthConfig, err := p.config.BuildOAuthConfig(env.ActiveDirectoryEndpoint)
	if err != nil {
		return nil, err
	}

	if oauthConfig == nil {
		return nil, fmt.Errorf("Unable to configure OAuthConfig for tenant %s", p.config.TenantID)
	}

	sender := sender.BuildSender("AzureRM")

	auth, err := p.config.GetAuthorizationToken(sender, oauthConfig, env.ResourceManagerEndpoint)
	if err != nil {
		return nil, err
	}

	return auth, nil
}

func (p *AzureProvider) Init(args []string) error {
	err := p.setEnvConfig()
	if err != nil {
		return err
	}

	authorizer, err := p.getAuthorizer()
	if err != nil {
		return err
	}
	p.authorizer = authorizer

	return nil
}

func (p *AzureProvider) GetName() string {
	return "azurerm"
}

func (p *AzureProvider) GetProviderData(arg ...string) map[string]interface{} {
	version := providerwrapper.GetProviderVersion(p.GetName())
	if strings.Contains(version, "v2.") {
		return map[string]interface{}{
			"provider": map[string]interface{}{
				"azurerm": map[string]interface{}{
					"version": version,
					// NOTE:
					// Workaround for azurerm v2 provider changes
					// Tested with azurerm_resource_group under v2.17.0
					// https://github.com/terraform-providers/terraform-provider-azurerm/issues/5866#issuecomment-594239342
					// https://github.com/hashicorp/terraform/issues/24200#issuecomment-594745861
					"features": map[string]interface{}{},
				},
			},
		}
	}
	return map[string]interface{}{
		"provider": map[string]interface{}{
			"azurerm": map[string]interface{}{
				"version": version,
			},
		},
	}
}

func (AzureProvider) GetResourceConnections() map[string]map[string][]string {
	return map[string]map[string][]string{}
}

func (p *AzureProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
	return map[string]terraformutils.ServiceGenerator{
		"app_service":                          &AppServiceGenerator{},
		"analysis":                             &AnalysisGenerator{},
		"cosmosdb":                             &CosmosDBGenerator{},
		"database":                             &DatabasesGenerator{},
		"disk":                                 &DiskGenerator{},
		"network_interface":                    &NetworkInterfaceGenerator{},
		"network_security_group":               &NetworkSecurityGroupGenerator{},
		"resource_group":                       &ResourceGroupGenerator{},
		"security_center_contact":              &SecurityCenterContactGenerator{},
		"security_center_subscription_pricing": &SecurityCenterSubscriptionPricingGenerator{},
		"storage_account":                      &StorageAccountGenerator{},
		"storage_container":                    &StorageContainerGenerator{},
		"storage_blob":                         &StorageBlobGenerator{},
		"virtual_machine":                      &VirtualMachineGenerator{},
		"virtual_network":                      &VirtualNetworkGenerator{},
	}
}

func (p *AzureProvider) InitService(serviceName string, verbose bool) error {
	var isSupported bool
	if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
		return errors.New("azurerm: " + serviceName + " not supported service")
	}
	p.Service = p.GetSupportedService()[serviceName]
	p.Service.SetName(serviceName)
	p.Service.SetVerbose(verbose)
	p.Service.SetProviderName(p.GetName())
	p.Service.SetArgs(map[string]interface{}{
		"config":     p.config,
		"authorizer": p.authorizer,
	})
	return nil
}
<commit_msg>removed app_service from azure_provider.go<commit_after>// Copyright 2019 The Terraformer 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 azure

import (
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/Azure/go-autorest/autorest"
	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
	"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
	"github.com/hashicorp/go-azure-helpers/authentication"
	"github.com/hashicorp/go-azure-helpers/sender"
)

type AzureProvider struct { //nolint
	terraformutils.Provider
	config     authentication.Config
	authorizer autorest.Authorizer
}

func (p *AzureProvider) setEnvConfig() error {
	subscriptionID := os.Getenv("ARM_SUBSCRIPTION_ID")
	if subscriptionID == "" {
		return errors.New("set ARM_SUBSCRIPTION_ID env var")
	}
	builder := &authentication.Builder{
		ClientID:                 os.Getenv("ARM_CLIENT_ID"),
		SubscriptionID:           subscriptionID,
		TenantID:                 os.Getenv("ARM_TENANT_ID"),
		Environment:              os.Getenv("ARM_ENVIRONMENT"),
		ClientSecret:             os.Getenv("ARM_CLIENT_SECRET"),
		SupportsAzureCliToken:    true,
		SupportsClientSecretAuth: true,
		SupportsClientCertAuth:   true,
		ClientCertPath:           os.Getenv("ARM_CLIENT_CERTIFICATE_PATH"),
		ClientCertPassword:       os.Getenv("ARM_CLIENT_CERTIFICATE_PASSWORD"),

		/*
		   // Managed Service Identity Auth
		   SupportsManagedServiceIdentity bool
		   MsiEndpoint                    string
		*/
	}

	if builder.Environment == "" {
		builder.Environment = "public"
	}
	config, err := builder.Build()
	if err != nil {
		return nil
	}
	p.config = *config

	return nil
}

func (p *AzureProvider) getAuthorizer() (autorest.Authorizer, error) {
	env, err := authentication.DetermineEnvironment(p.config.Environment)
	if err != nil {
		return nil, err
	}

	oauthConfig, err := p.config.BuildOAuthConfig(env.ActiveDirectoryEndpoint)
	if err != nil {
		return nil, err
	}

	if oauthConfig == nil {
		return nil, fmt.Errorf("Unable to configure OAuthConfig for tenant %s", p.config.TenantID)
	}

	sender := sender.BuildSender("AzureRM")

	auth, err := p.config.GetAuthorizationToken(sender, oauthConfig, env.ResourceManagerEndpoint)
	if err != nil {
		return nil, err
	}

	return auth, nil
}

func (p *AzureProvider) Init(args []string) error {
	err := p.setEnvConfig()
	if err != nil {
		return err
	}

	authorizer, err := p.getAuthorizer()
	if err != nil {
		return err
	}
	p.authorizer = authorizer

	return nil
}

func (p *AzureProvider) GetName() string {
	return "azurerm"
}

func (p *AzureProvider) GetProviderData(arg ...string) map[string]interface{} {
	version := providerwrapper.GetProviderVersion(p.GetName())
	if strings.Contains(version, "v2.") {
		return map[string]interface{}{
			"provider": map[string]interface{}{
				"azurerm": map[string]interface{}{
					"version": version,
					// NOTE:
					// Workaround for azurerm v2 provider changes
					// Tested with azurerm_resource_group under v2.17.0
					// https://github.com/terraform-providers/terraform-provider-azurerm/issues/5866#issuecomment-594239342
					// https://github.com/hashicorp/terraform/issues/24200#issuecomment-594745861
					"features": map[string]interface{}{},
				},
			},
		}
	}
	return map[string]interface{}{
		"provider": map[string]interface{}{
			"azurerm": map[string]interface{}{
				"version": version,
			},
		},
	}
}

func (AzureProvider) GetResourceConnections() map[string]map[string][]string {
	return map[string]map[string][]string{}
}

func (p *AzureProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
	return map[string]terraformutils.ServiceGenerator{
		"analysis":                             &AnalysisGenerator{},
		"cosmosdb":                             &CosmosDBGenerator{},
		"database":                             &DatabasesGenerator{},
		"disk":                                 &DiskGenerator{},
		"network_interface":                    &NetworkInterfaceGenerator{},
		"network_security_group":               &NetworkSecurityGroupGenerator{},
		"resource_group":                       &ResourceGroupGenerator{},
		"security_center_contact":              &SecurityCenterContactGenerator{},
		"security_center_subscription_pricing": &SecurityCenterSubscriptionPricingGenerator{},
		"storage_account":                      &StorageAccountGenerator{},
		"storage_container":                    &StorageContainerGenerator{},
		"storage_blob":                         &StorageBlobGenerator{},
		"virtual_machine":                      &VirtualMachineGenerator{},
		"virtual_network":                      &VirtualNetworkGenerator{},
	}
}

func (p *AzureProvider) InitService(serviceName string, verbose bool) error {
	var isSupported bool
	if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
		return errors.New("azurerm: " + serviceName + " not supported service")
	}
	p.Service = p.GetSupportedService()[serviceName]
	p.Service.SetName(serviceName)
	p.Service.SetVerbose(verbose)
	p.Service.SetProviderName(p.GetName())
	p.Service.SetArgs(map[string]interface{}{
		"config":     p.config,
		"authorizer": p.authorizer,
	})
	return nil
}
<|endoftext|>


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

package pool

import (
	"reflect"

	"github.com/tsuru/tsuru/provision/pool"
	check "gopkg.in/check.v1"
	"gopkg.in/mgo.v2/bson"
)

func (s *S) TestSetPoolConstraints(c *check.C) {
	coll := s.storage.PoolsConstraints()
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb", "hipache"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeTeam, Values: []string{"user"}, Blacklist: true})
	c.Assert(err, check.IsNil)
	var cs []*PoolConstraint
	err = coll.Find(bson.M{"poolexpr": "*"}).All(&cs)
	c.Assert(err, check.IsNil)
	c.Assert(cs, check.DeepEquals, []*PoolConstraint{
		{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb", "hipache"}},
		{PoolExpr: "*", Field: ConstraintTypeTeam, Values: []string{"user"}, Blacklist: true},
	})
}

func (s *S) TestSetPoolConstraintsWithServices(c *check.C) {
	coll := s.storage.PoolsConstraints()
	err := SetPoolConstraint(&PoolConstraint{
		PoolExpr: "prod",
		Field:    pool.ConstraintTypeService,
		Values:   []string{"lux"},
	})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{
		PoolExpr: "dev",
		Field:    pool.ConstraintTypeService,
		Values:   []string{"demacia"},
	})
	c.Assert(err, check.IsNil)
	var cs []*PoolConstraint
	err = coll.Find(bson.M{"field": "service"}).All(&cs)
	c.Assert(err, check.IsNil)
	c.Assert(cs, check.DeepEquals, []*PoolConstraint{
		{PoolExpr: "prod", Field: ConstraintTypeService, Values: []string{"lux"}},
		{PoolExpr: "dev", Field: ConstraintTypeService, Values: []string{"demacia"}},
	})
}

func (s *S) TestSetPoolConstraintsRemoveEmpty(c *check.C) {
	coll := s.storage.PoolsConstraints()
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb", "hipache"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeTeam, Values: []string{"user"}, Blacklist: true})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeTeam, Values: []string{""}})
	c.Assert(err, check.IsNil)
	var cs []*PoolConstraint
	err = coll.Find(bson.M{"poolexpr": "*"}).All(&cs)
	c.Assert(err, check.IsNil)
	c.Assert(cs, check.DeepEquals, []*PoolConstraint{
		{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb", "hipache"}},
	})
}

func (s *S) TestSetPoolConstraintInvalidConstraintType(c *check.C) {
	coll := s.storage.PoolsConstraints()
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: "invalid", Values: []string{"abc"}, Blacklist: true})
	c.Assert(err, check.Equals, ErrInvalidConstraintType)
	var cs []*PoolConstraint
	err = coll.Find(bson.M{"poolexpr": "*"}).All(&cs)
	c.Assert(err, check.IsNil)
	c.Assert(len(cs), check.Equals, 0)
}

func (s *S) TestGetConstraintsForPool(c *check.C) {
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "pp", Field: ConstraintTypeRouter, Values: []string{"galeb"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*_dev", Field: ConstraintTypeRouter, Values: []string{"planb_dev"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*_dev", Field: ConstraintTypeTeam, Values: []string{"team_pool1"}, Blacklist: true})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "pool1_dev", Field: ConstraintTypeTeam, Values: []string{"team_pool1"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "pool1\\x", Field: ConstraintTypeTeam, Values: []string{"team_pool1x"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*\\xdev", Field: ConstraintTypeTeam, Values: []string{"team_xdev"}})
	c.Assert(err, check.IsNil)
	tt := []struct {
		pool     string
		expected map[poolConstraintType]*PoolConstraint
	}{
		{pool: "prod", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}},
		}},
		{pool: "pp", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "pp", Field: ConstraintTypeRouter, Values: []string{"galeb"}},
		}},
		{pool: "pool1_dev", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*_dev", Field: ConstraintTypeRouter, Values: []string{"planb_dev"}},
			ConstraintTypeTeam:   {PoolExpr: "pool1_dev", Field: ConstraintTypeTeam, Values: []string{"team_pool1"}},
		}},
		{pool: "pool2_dev", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*_dev", Field: ConstraintTypeRouter, Values: []string{"planb_dev"}},
			ConstraintTypeTeam:   {PoolExpr: "*_dev", Field: ConstraintTypeTeam, Values: []string{"team_pool1"}, Blacklist: true},
		}},
		{pool: "pp2", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}},
		}},
		{pool: "pool1\\x", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}},
			ConstraintTypeTeam:   {PoolExpr: "pool1\\x", Field: ConstraintTypeTeam, Values: []string{"team_pool1x"}},
		}},
		{pool: "abc\\xdev", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}},
			ConstraintTypeTeam:   {PoolExpr: "*\\xdev", Field: ConstraintTypeTeam, Values: []string{"team_xdev"}},
		}},
	}
	for i, t := range tt {
		constraints, err := getConstraintsForPool(t.pool)
		c.Check(err, check.IsNil)
		if !reflect.DeepEqual(constraints, t.expected) {
			c.Fatalf("(%d) Expected %#+v for pool %q. Got %#+v.", i, t.expected, t.pool, constraints)
		}
	}
}

func (s *S) TestAppendPoolConstraint(c *check.C) {
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}, Blacklist: true})
	c.Assert(err, check.IsNil)
	err = AppendPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"galeb"}})
	c.Assert(err, check.IsNil)
	err = AppendPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeService, Values: []string{"autoscale"}})
	c.Assert(err, check.IsNil)
	err = AppendPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: "invalid", Values: []string{"val"}})
	c.Assert(err, check.Equals, ErrInvalidConstraintType)
	constraints, err := getConstraintsForPool("*")
	c.Assert(err, check.IsNil)
	c.Assert(constraints, check.DeepEquals, map[poolConstraintType]*PoolConstraint{
		ConstraintTypeRouter:  {Field: ConstraintTypeRouter, PoolExpr: "*", Values: []string{"planb", "galeb"}, Blacklist: true},
		ConstraintTypeService: {Field: ConstraintTypeService, PoolExpr: "*", Values: []string{"autoscale"}},
	})
}

func (s *S) TestAppendPoolConstraintNewConstraint(c *check.C) {
	err := AppendPoolConstraint(&PoolConstraint{PoolExpr: "myPool", Field: ConstraintTypeRouter, Values: []string{"galeb"}})
	c.Assert(err, check.IsNil)
	constraints, err := getConstraintsForPool("myPool")
	c.Assert(err, check.IsNil)
	c.Assert(constraints, check.DeepEquals, map[poolConstraintType]*PoolConstraint{
		ConstraintTypeRouter: {Field: ConstraintTypeRouter, PoolExpr: "myPool", Values: []string{"galeb"}},
	})
}
<commit_msg>provision/pool: fix import cycle<commit_after>// Copyright 2017 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pool

import (
	"reflect"

	check "gopkg.in/check.v1"
	"gopkg.in/mgo.v2/bson"
)

func (s *S) TestSetPoolConstraints(c *check.C) {
	coll := s.storage.PoolsConstraints()
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb", "hipache"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeTeam, Values: []string{"user"}, Blacklist: true})
	c.Assert(err, check.IsNil)
	var cs []*PoolConstraint
	err = coll.Find(bson.M{"poolexpr": "*"}).All(&cs)
	c.Assert(err, check.IsNil)
	c.Assert(cs, check.DeepEquals, []*PoolConstraint{
		{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb", "hipache"}},
		{PoolExpr: "*", Field: ConstraintTypeTeam, Values: []string{"user"}, Blacklist: true},
	})
}

func (s *S) TestSetPoolConstraintsWithServices(c *check.C) {
	coll := s.storage.PoolsConstraints()
	err := SetPoolConstraint(&PoolConstraint{
		PoolExpr: "prod",
		Field:    ConstraintTypeService,
		Values:   []string{"lux"},
	})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{
		PoolExpr: "dev",
		Field:    ConstraintTypeService,
		Values:   []string{"demacia"},
	})
	c.Assert(err, check.IsNil)
	var cs []*PoolConstraint
	err = coll.Find(bson.M{"field": "service"}).All(&cs)
	c.Assert(err, check.IsNil)
	c.Assert(cs, check.DeepEquals, []*PoolConstraint{
		{PoolExpr: "prod", Field: ConstraintTypeService, Values: []string{"lux"}},
		{PoolExpr: "dev", Field: ConstraintTypeService, Values: []string{"demacia"}},
	})
}

func (s *S) TestSetPoolConstraintsRemoveEmpty(c *check.C) {
	coll := s.storage.PoolsConstraints()
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb", "hipache"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeTeam, Values: []string{"user"}, Blacklist: true})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeTeam, Values: []string{""}})
	c.Assert(err, check.IsNil)
	var cs []*PoolConstraint
	err = coll.Find(bson.M{"poolexpr": "*"}).All(&cs)
	c.Assert(err, check.IsNil)
	c.Assert(cs, check.DeepEquals, []*PoolConstraint{
		{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb", "hipache"}},
	})
}

func (s *S) TestSetPoolConstraintInvalidConstraintType(c *check.C) {
	coll := s.storage.PoolsConstraints()
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: "invalid", Values: []string{"abc"}, Blacklist: true})
	c.Assert(err, check.Equals, ErrInvalidConstraintType)
	var cs []*PoolConstraint
	err = coll.Find(bson.M{"poolexpr": "*"}).All(&cs)
	c.Assert(err, check.IsNil)
	c.Assert(len(cs), check.Equals, 0)
}

func (s *S) TestGetConstraintsForPool(c *check.C) {
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "pp", Field: ConstraintTypeRouter, Values: []string{"galeb"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*_dev", Field: ConstraintTypeRouter, Values: []string{"planb_dev"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*_dev", Field: ConstraintTypeTeam, Values: []string{"team_pool1"}, Blacklist: true})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "pool1_dev", Field: ConstraintTypeTeam, Values: []string{"team_pool1"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "pool1\\x", Field: ConstraintTypeTeam, Values: []string{"team_pool1x"}})
	c.Assert(err, check.IsNil)
	err = SetPoolConstraint(&PoolConstraint{PoolExpr: "*\\xdev", Field: ConstraintTypeTeam, Values: []string{"team_xdev"}})
	c.Assert(err, check.IsNil)
	tt := []struct {
		pool     string
		expected map[poolConstraintType]*PoolConstraint
	}{
		{pool: "prod", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}},
		}},
		{pool: "pp", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "pp", Field: ConstraintTypeRouter, Values: []string{"galeb"}},
		}},
		{pool: "pool1_dev", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*_dev", Field: ConstraintTypeRouter, Values: []string{"planb_dev"}},
			ConstraintTypeTeam:   {PoolExpr: "pool1_dev", Field: ConstraintTypeTeam, Values: []string{"team_pool1"}},
		}},
		{pool: "pool2_dev", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*_dev", Field: ConstraintTypeRouter, Values: []string{"planb_dev"}},
			ConstraintTypeTeam:   {PoolExpr: "*_dev", Field: ConstraintTypeTeam, Values: []string{"team_pool1"}, Blacklist: true},
		}},
		{pool: "pp2", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}},
		}},
		{pool: "pool1\\x", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}},
			ConstraintTypeTeam:   {PoolExpr: "pool1\\x", Field: ConstraintTypeTeam, Values: []string{"team_pool1x"}},
		}},
		{pool: "abc\\xdev", expected: map[poolConstraintType]*PoolConstraint{
			ConstraintTypeRouter: {PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}},
			ConstraintTypeTeam:   {PoolExpr: "*\\xdev", Field: ConstraintTypeTeam, Values: []string{"team_xdev"}},
		}},
	}
	for i, t := range tt {
		constraints, err := getConstraintsForPool(t.pool)
		c.Check(err, check.IsNil)
		if !reflect.DeepEqual(constraints, t.expected) {
			c.Fatalf("(%d) Expected %#+v for pool %q. Got %#+v.", i, t.expected, t.pool, constraints)
		}
	}
}

func (s *S) TestAppendPoolConstraint(c *check.C) {
	err := SetPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"planb"}, Blacklist: true})
	c.Assert(err, check.IsNil)
	err = AppendPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeRouter, Values: []string{"galeb"}})
	c.Assert(err, check.IsNil)
	err = AppendPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: ConstraintTypeService, Values: []string{"autoscale"}})
	c.Assert(err, check.IsNil)
	err = AppendPoolConstraint(&PoolConstraint{PoolExpr: "*", Field: "invalid", Values: []string{"val"}})
	c.Assert(err, check.Equals, ErrInvalidConstraintType)
	constraints, err := getConstraintsForPool("*")
	c.Assert(err, check.IsNil)
	c.Assert(constraints, check.DeepEquals, map[poolConstraintType]*PoolConstraint{
		ConstraintTypeRouter:  {Field: ConstraintTypeRouter, PoolExpr: "*", Values: []string{"planb", "galeb"}, Blacklist: true},
		ConstraintTypeService: {Field: ConstraintTypeService, PoolExpr: "*", Values: []string{"autoscale"}},
	})
}

func (s *S) TestAppendPoolConstraintNewConstraint(c *check.C) {
	err := AppendPoolConstraint(&PoolConstraint{PoolExpr: "myPool", Field: ConstraintTypeRouter, Values: []string{"galeb"}})
	c.Assert(err, check.IsNil)
	constraints, err := getConstraintsForPool("myPool")
	c.Assert(err, check.IsNil)
	c.Assert(constraints, check.DeepEquals, map[poolConstraintType]*PoolConstraint{
		ConstraintTypeRouter: {Field: ConstraintTypeRouter, PoolExpr: "myPool", Values: []string{"galeb"}},
	})
}
<|endoftext|>


<commit_before>package logsearcher

import(
  "strings"
)

func LogEntryPredicate(usernameMixedCase string, messageMixedCase string) Predicate {
  username := strings.ToLower(usernameMixedCase)
  message := strings.ToLower(messageMixedCase)

  return func(strMixedCase string) bool {
    str := strings.ToLower(strMixedCase)
    fields := strings.Fields(str)

    return len(fields) > 1 &&
      (len(username) == 0 || username + ":" == fields[1]) &&
      strings.Contains(str, message)
  }
}
<commit_msg>Support old-format usernames<commit_after>package logsearcher

import(
  "strings"
)

func LogEntryPredicate(usernameMixedCase string, messageMixedCase string) Predicate {
  username := strings.ToLower(usernameMixedCase)
  message := strings.ToLower(messageMixedCase)

  return func(strMixedCase string) bool {
    str := strings.ToLower(strMixedCase)
    fields := strings.Fields(str)

    return len(fields) > 1 &&
      (len(username) == 0 || username + ":" == fields[1] || "<" + username + ">" == fields[1]) &&
      strings.Contains(str, message)
  }
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/atotto/clipboard"
	"github.com/oakmound/oak/v3"
	"github.com/oakmound/oak/v3/entities/x/btn"
	"github.com/oakmound/oak/v3/event"
	"github.com/oakmound/oak/v3/key"
	"github.com/oakmound/oak/v3/mouse"
	"github.com/oakmound/oak/v3/render"
	"github.com/oakmound/oak/v3/scene"
	gokey "golang.org/x/mobile/event/key"
)

func main() {
	oak.AddScene("clipboard-test", scene.Scene{
		Start: func(ctx *scene.Context) {
			newClipboardCopyText("click-me-to-copy", 20, 20)
			newClipboardCopyText("click-to-copy-me-too", 20, 50)
			newClipboardPaster("click-or-ctrl+v-to-paste-here", 20, 200)
		},
	})
	oak.Init("clipboard-test")
}

func newClipboardCopyText(text string, x, y float64) {
	btn.New(
		btn.Font(render.DefaultFont()),
		btn.Text(text),
		btn.Pos(x, y),
		btn.Height(20),
		btn.FitText(20),
		btn.Click(func(b btn.Btn, me *mouse.Event) event.Response {
			err := clipboard.WriteAll(text)
			if err != nil {
				fmt.Println(err)
			}
			return 0
		}),
	)
}

func newClipboardPaster(placeholder string, x, y float64) {
	textPtr := new(string)
	*textPtr = placeholder

	btn.New(
		btn.Font(render.DefaultFont()),
		btn.TextPtr(textPtr),
		btn.Pos(x, y),
		btn.Height(20),
		btn.FitText(20),
		btn.Binding(key.Down(key.V), func(b btn.Btn, kv key.Event) event.Response {

			if kv.Modifiers&gokey.ModControl == gokey.ModControl {
				got, err := clipboard.ReadAll()
				if err != nil {
					fmt.Println(err)
					return 0
				}
				*textPtr = got
			}
			return 0
		}),
		btn.Click(func(b btn.Btn, me *mouse.Event) event.Response {
			got, err := clipboard.ReadAll()
			if err != nil {
				fmt.Println(err)
				return 0
			}
			*textPtr = got
			return 0
		}),
	)
}
<commit_msg>examples/clipboard: remove mobile key import<commit_after>package main

import (
	"fmt"

	"github.com/atotto/clipboard"
	"github.com/oakmound/oak/v3"
	"github.com/oakmound/oak/v3/entities/x/btn"
	"github.com/oakmound/oak/v3/event"
	"github.com/oakmound/oak/v3/key"
	"github.com/oakmound/oak/v3/mouse"
	"github.com/oakmound/oak/v3/render"
	"github.com/oakmound/oak/v3/scene"
)

func main() {
	oak.AddScene("clipboard-test", scene.Scene{
		Start: func(ctx *scene.Context) {
			newClipboardCopyText("click-me-to-copy", 20, 20)
			newClipboardCopyText("click-to-copy-me-too", 20, 50)
			newClipboardPaster("click-or-ctrl+v-to-paste-here", 20, 200)
		},
	})
	oak.Init("clipboard-test")
}

func newClipboardCopyText(text string, x, y float64) {
	btn.New(
		btn.Font(render.DefaultFont()),
		btn.Text(text),
		btn.Pos(x, y),
		btn.Height(20),
		btn.FitText(20),
		btn.Click(func(b btn.Btn, me *mouse.Event) event.Response {
			err := clipboard.WriteAll(text)
			if err != nil {
				fmt.Println(err)
			}
			return 0
		}),
	)
}

func newClipboardPaster(placeholder string, x, y float64) {
	textPtr := new(string)
	*textPtr = placeholder

	btn.New(
		btn.Font(render.DefaultFont()),
		btn.TextPtr(textPtr),
		btn.Pos(x, y),
		btn.Height(20),
		btn.FitText(20),
		btn.Binding(key.Down(key.V), func(b btn.Btn, kv key.Event) event.Response {

			if kv.Modifiers&key.ModControl == key.ModControl {
				got, err := clipboard.ReadAll()
				if err != nil {
					fmt.Println(err)
					return 0
				}
				*textPtr = got
			}
			return 0
		}),
		btn.Click(func(b btn.Btn, me *mouse.Event) event.Response {
			got, err := clipboard.ReadAll()
			if err != nil {
				fmt.Println(err)
				return 0
			}
			*textPtr = got
			return 0
		}),
	)
}
<|endoftext|>


<commit_before>// Port of http://members.shaw.ca/el.supremo/MagickWand/floodfill.htm to Go
package main

import (
	"github.com/gographics/imagick/imagick"
	"os"
)

func main() {
	imagick.Initialize()
	defer imagick.Terminate()

	var err error

	mw := imagick.NewMagickWand()
	defer mw.Destroy()

	// fillcolor and bordercolor
	fc, bc := imagick.NewPixelWand(), imagick.NewPixelWand()
	defer fc.Destroy()
	defer bc.Destroy()

	fc.SetColor("none")
	bc.SetColor("white")

	err = mw.ReadImage("logo:")
	if err != nil {
		panic(err)
	}

	rgba := imagick.RedChannel | imagick.GreenChannel | imagick.BlueChannel | imagick.AlphaChannel

	// The bordercolor (with fuzz of 20 applied) is replaced by the fill
	// colour starting at the given coordinate - in this case 0, 0.
	// Normally the last argument is false so that the colours are matched
	// but if it is true then it floodfills any pixel that does *not* match
	// the target color
	mw.FloodfillPaintImage(rgba, fc, 20, bc, 0, 0, false)

	mw.DisplayImage(os.Getenv("DYSPLAY"))
	if err != nil {
		panic(err)
	}
}
<commit_msg>Fix constant names<commit_after>// Port of http://members.shaw.ca/el.supremo/MagickWand/floodfill.htm to Go
package main

import (
	"github.com/gographics/imagick/imagick"
	"os"
)

func main() {
	imagick.Initialize()
	defer imagick.Terminate()

	var err error

	mw := imagick.NewMagickWand()
	defer mw.Destroy()

	// fillcolor and bordercolor
	fc, bc := imagick.NewPixelWand(), imagick.NewPixelWand()
	defer fc.Destroy()
	defer bc.Destroy()

	fc.SetColor("none")
	bc.SetColor("white")

	err = mw.ReadImage("logo:")
	if err != nil {
		panic(err)
	}

	rgba := imagick.CHANNELS_RGB | imagick.CHANNEL_ALPHA

	// The bordercolor (with fuzz of 20 applied) is replaced by the fill
	// colour starting at the given coordinate - in this case 0, 0.
	// Normally the last argument is false so that the colours are matched
	// but if it is true then it floodfills any pixel that does *not* match
	// the target color
	mw.FloodfillPaintImage(rgba, fc, 20, bc, 0, 0, false)

	mw.DisplayImage(os.Getenv("DYSPLAY"))
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 trivago GmbH
//
// 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 format

import (
	"strings"

	"github.com/trivago/gollum/core"
)

// MetadataCopy formatter plugin
//
// This formatter sets metadata fields by copying data from the message's
// payload or from other metadata fields.
//
// Parameters
//
// - Key: Defines the key to copy, i.e. the "source". ApplyTo will define
// the target of the copy, i.e. the "destination". An empty string will
// use the message payload as source.
// By default this parameter is set to an empty string (i.e. payload).
//
// - Mode: Defines the copy mode to use. This can be one of "append",
// "prepend" or "replace".
// By default this parameter is set to "replace".
//
// - Separator: When using mode prepend or append, defines the characters
// inserted between source and destination.
// By default this parameter is set to an empty string.
//
// - CopyToKeys: DEPRECATED. A list of meta data keys to copy the payload
// or metadata content to. If this field contains at least one value, mode
// is set to replace and the key field is ignored.
// By default this parameter is set to an empty list.
//
// Examples
//
// This example copies the payload to the field key and applies a hash on
// it contain a hash over the complete payload.
//
//  exampleConsumer:
//    Type: consumer.Console
//    Streams: "*"
//    Modulators:
//      - format.MetadataCopy:
//        ApplyTo: key
//      - formatter.Identifier
//        Generator: hash
//        ApplyTo: key
//
type MetadataCopy struct {
	core.SimpleFormatter `gollumdoc:"embed_type"`
	key                  string   `config:"Key"`
	separator            []byte   `config:"Separator"`
	metaDataKeys         []string `config:"CopyToKeys"` // deprecated
	mode                 metadataCopyMode
}

type metadataCopyMode int

const (
	metadataCopyModeAppend  = metadataCopyMode(iota)
	metadataCopyModeReplace = metadataCopyMode(iota)
	metadataCopyModePrepend = metadataCopyMode(iota)
)

func init() {
	core.TypeRegistry.Register(MetadataCopy{})
}

// Configure initializes this formatter with values from a plugin config.
func (format *MetadataCopy) Configure(conf core.PluginConfigReader) {
	mode := conf.GetString("Mode", "replace")
	switch strings.ToLower(mode) {
	case "replace":
		format.mode = metadataCopyModeReplace
	case "append":
		format.mode = metadataCopyModeAppend
	case "prepend":
		format.mode = metadataCopyModePrepend
	default:
		conf.Errors.Pushf("mode must be one of replace, append or prepend")
	}
}

// ApplyFormatter update message payload
func (format *MetadataCopy) ApplyFormatter(msg *core.Message) error {

	if len(format.metaDataKeys) > 0 {
		// DEPRECATED
		// This codepath will be removed in 0.6
		meta := msg.GetMetadata()
		data := format.GetAppliedContent(msg)
		pool := core.MessageDataPool

		for _, key := range format.metaDataKeys {
			bufferCopy := pool.Get(len(data))
			copy(bufferCopy, data)
			meta.SetValue(key, bufferCopy)
		}
		return nil
	}

	getSourceData := core.GetAppliedContentGetFunction(format.key)
	srcData := getSourceData(msg)

	println(format.key, ":", string(srcData))

	switch format.mode {
	case metadataCopyModeReplace:
		format.SetAppliedContent(msg, srcData)

	case metadataCopyModePrepend:
		dstData := format.GetAppliedContent(msg)
		if len(format.separator) != 0 {
			srcData = append(srcData, format.separator...)
		}
		format.SetAppliedContent(msg, append(srcData, dstData...))

	case metadataCopyModeAppend:
		dstData := format.GetAppliedContent(msg)
		if len(format.separator) != 0 {
			dstData = append(dstData, format.separator...)
		}
		format.SetAppliedContent(msg, append(dstData, srcData...))
	}

	return nil
}
<commit_msg>remove println<commit_after>// Copyright 2015-2017 trivago GmbH
//
// 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 format

import (
	"strings"

	"github.com/trivago/gollum/core"
)

// MetadataCopy formatter plugin
//
// This formatter sets metadata fields by copying data from the message's
// payload or from other metadata fields.
//
// Parameters
//
// - Key: Defines the key to copy, i.e. the "source". ApplyTo will define
// the target of the copy, i.e. the "destination". An empty string will
// use the message payload as source.
// By default this parameter is set to an empty string (i.e. payload).
//
// - Mode: Defines the copy mode to use. This can be one of "append",
// "prepend" or "replace".
// By default this parameter is set to "replace".
//
// - Separator: When using mode prepend or append, defines the characters
// inserted between source and destination.
// By default this parameter is set to an empty string.
//
// - CopyToKeys: DEPRECATED. A list of meta data keys to copy the payload
// or metadata content to. If this field contains at least one value, mode
// is set to replace and the key field is ignored.
// By default this parameter is set to an empty list.
//
// Examples
//
// This example copies the payload to the field key and applies a hash on
// it contain a hash over the complete payload.
//
//  exampleConsumer:
//    Type: consumer.Console
//    Streams: "*"
//    Modulators:
//      - format.MetadataCopy:
//        ApplyTo: key
//      - formatter.Identifier
//        Generator: hash
//        ApplyTo: key
//
type MetadataCopy struct {
	core.SimpleFormatter `gollumdoc:"embed_type"`
	key                  string   `config:"Key"`
	separator            []byte   `config:"Separator"`
	metaDataKeys         []string `config:"CopyToKeys"` // deprecated
	mode                 metadataCopyMode
}

type metadataCopyMode int

const (
	metadataCopyModeAppend  = metadataCopyMode(iota)
	metadataCopyModeReplace = metadataCopyMode(iota)
	metadataCopyModePrepend = metadataCopyMode(iota)
)

func init() {
	core.TypeRegistry.Register(MetadataCopy{})
}

// Configure initializes this formatter with values from a plugin config.
func (format *MetadataCopy) Configure(conf core.PluginConfigReader) {
	mode := conf.GetString("Mode", "replace")
	switch strings.ToLower(mode) {
	case "replace":
		format.mode = metadataCopyModeReplace
	case "append":
		format.mode = metadataCopyModeAppend
	case "prepend":
		format.mode = metadataCopyModePrepend
	default:
		conf.Errors.Pushf("mode must be one of replace, append or prepend")
	}
}

// ApplyFormatter update message payload
func (format *MetadataCopy) ApplyFormatter(msg *core.Message) error {

	if len(format.metaDataKeys) > 0 {
		// DEPRECATED
		// This codepath will be removed in 0.6
		meta := msg.GetMetadata()
		data := format.GetAppliedContent(msg)
		pool := core.MessageDataPool

		for _, key := range format.metaDataKeys {
			bufferCopy := pool.Get(len(data))
			copy(bufferCopy, data)
			meta.SetValue(key, bufferCopy)
		}
		return nil
	}

	getSourceData := core.GetAppliedContentGetFunction(format.key)
	srcData := getSourceData(msg)

	switch format.mode {
	case metadataCopyModeReplace:
		format.SetAppliedContent(msg, srcData)

	case metadataCopyModePrepend:
		dstData := format.GetAppliedContent(msg)
		if len(format.separator) != 0 {
			srcData = append(srcData, format.separator...)
		}
		format.SetAppliedContent(msg, append(srcData, dstData...))

	case metadataCopyModeAppend:
		dstData := format.GetAppliedContent(msg)
		if len(format.separator) != 0 {
			dstData = append(dstData, format.separator...)
		}
		format.SetAppliedContent(msg, append(dstData, srcData...))
	}

	return nil
}
<|endoftext|>