<commit_before>package rootfs

import (
	"fmt"

	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/log"
	"github.com/containerd/containerd/mount"
	"github.com/containerd/containerd/snapshot"
	"github.com/opencontainers/go-digest"
	"github.com/opencontainers/image-spec/identity"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
)

type Applier interface {
	Apply(context.Context, ocispec.Descriptor, []mount.Mount) (ocispec.Descriptor, error)
}

type Layer struct {
	Diff ocispec.Descriptor
	Blob ocispec.Descriptor
}

func ApplyLayers(ctx context.Context, layers []Layer, sn snapshot.Snapshotter, a Applier) (digest.Digest, error) {
	var chain []digest.Digest
	for _, layer := range layers {
		if err := applyLayer(ctx, layer, chain, sn, a); err != nil {
			// TODO: possibly wait and retry if extraction of same chain id was in progress
			return "", err
		}

		chain = append(chain, layer.Diff.Digest)
	}
	return identity.ChainID(chain), nil
}

func applyLayer(ctx context.Context, layer Layer, chain []digest.Digest, sn snapshot.Snapshotter, a Applier) error {
	var (
		parent  = identity.ChainID(chain)
		chainID = identity.ChainID(append(chain, layer.Diff.Digest))
		diff    ocispec.Descriptor
	)

	_, err := sn.Stat(ctx, chainID.String())
	if err == nil {
		log.G(ctx).Debugf("Extraction not needed, layer snapshot exists")
		return nil
	} else if !errdefs.IsNotFound(err) {
		return errors.Wrap(err, "failed to stat snapshot")
	}

	key := fmt.Sprintf("extract %s", chainID)

	// Prepare snapshot with from parent
	mounts, err := sn.Prepare(ctx, key, parent.String())
	if err != nil {
		//TODO: If is snapshot exists error, retry
		return errors.Wrap(err, "failed to prepare extraction layer")
	}
	defer func() {
		if err != nil {
			log.G(ctx).WithError(err).WithField("key", key).Infof("Apply failure, attempting cleanup")
			if rerr := sn.Remove(ctx, key); rerr != nil {
				log.G(ctx).WithError(rerr).Warnf("Extraction snapshot %q removal failed: %v", key)
			}
		}
	}()

	diff, err = a.Apply(ctx, layer.Blob, mounts)
	if err != nil {
		return errors.Wrapf(err, "failed to extract layer %s", layer.Diff.Digest)
	}
	if diff.Digest != layer.Diff.Digest {
		err = errors.Errorf("wrong diff id calculated on extraction %q", diff.Digest)
		return err
	}

	if err = sn.Commit(ctx, chainID.String(), key); err != nil {
		return errors.Wrapf(err, "failed to commit snapshot %s", parent)
	}

	return nil
}
<commit_msg>Fix rootfs error message extra format variable<commit_after>package rootfs

import (
	"fmt"

	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/log"
	"github.com/containerd/containerd/mount"
	"github.com/containerd/containerd/snapshot"
	"github.com/opencontainers/go-digest"
	"github.com/opencontainers/image-spec/identity"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
)

type Applier interface {
	Apply(context.Context, ocispec.Descriptor, []mount.Mount) (ocispec.Descriptor, error)
}

type Layer struct {
	Diff ocispec.Descriptor
	Blob ocispec.Descriptor
}

func ApplyLayers(ctx context.Context, layers []Layer, sn snapshot.Snapshotter, a Applier) (digest.Digest, error) {
	var chain []digest.Digest
	for _, layer := range layers {
		if err := applyLayer(ctx, layer, chain, sn, a); err != nil {
			// TODO: possibly wait and retry if extraction of same chain id was in progress
			return "", err
		}

		chain = append(chain, layer.Diff.Digest)
	}
	return identity.ChainID(chain), nil
}

func applyLayer(ctx context.Context, layer Layer, chain []digest.Digest, sn snapshot.Snapshotter, a Applier) error {
	var (
		parent  = identity.ChainID(chain)
		chainID = identity.ChainID(append(chain, layer.Diff.Digest))
		diff    ocispec.Descriptor
	)

	_, err := sn.Stat(ctx, chainID.String())
	if err == nil {
		log.G(ctx).Debugf("Extraction not needed, layer snapshot exists")
		return nil
	} else if !errdefs.IsNotFound(err) {
		return errors.Wrap(err, "failed to stat snapshot")
	}

	key := fmt.Sprintf("extract %s", chainID)

	// Prepare snapshot with from parent
	mounts, err := sn.Prepare(ctx, key, parent.String())
	if err != nil {
		//TODO: If is snapshot exists error, retry
		return errors.Wrap(err, "failed to prepare extraction layer")
	}
	defer func() {
		if err != nil {
			log.G(ctx).WithError(err).WithField("key", key).Infof("Apply failure, attempting cleanup")
			if rerr := sn.Remove(ctx, key); rerr != nil {
				log.G(ctx).WithError(rerr).Warnf("Extraction snapshot %q removal failed", key)
			}
		}
	}()

	diff, err = a.Apply(ctx, layer.Blob, mounts)
	if err != nil {
		return errors.Wrapf(err, "failed to extract layer %s", layer.Diff.Digest)
	}
	if diff.Digest != layer.Diff.Digest {
		err = errors.Errorf("wrong diff id calculated on extraction %q", diff.Digest)
		return err
	}

	if err = sn.Commit(ctx, chainID.String(), key); err != nil {
		return errors.Wrapf(err, "failed to commit snapshot %s", parent)
	}

	return nil
}
<|endoftext|>


<commit_before>package router

import (
	"errors"
	"sync"
	"time"

	"github.com/google/uuid"
)

var (
	// ErrRouteNotFound is returned when no route was found in the routing table
	ErrRouteNotFound = errors.New("route not found")
	// ErrDuplicateRoute is returned when the route already exists
	ErrDuplicateRoute = errors.New("duplicate route")
)

// table is an in-memory routing table
type table struct {
	sync.RWMutex
	// routes stores service routes
	routes map[string]map[uint64]Route
	// watchers stores table watchers
	watchers map[string]*tableWatcher
}

// newtable creates a new routing table and returns it
func newTable(opts ...Option) *table {
	return &table{
		routes:   make(map[string]map[uint64]Route),
		watchers: make(map[string]*tableWatcher),
	}
}

// sendEvent sends events to all subscribed watchers
func (t *table) sendEvent(e *Event) {
	t.RLock()
	defer t.RUnlock()

	for _, w := range t.watchers {
		select {
		case w.resChan <- e:
		case <-w.done:
		}
	}
}

// Create creates new route in the routing table
func (t *table) Create(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	// check if there are any routes in the table for the route destination
	if _, ok := t.routes[service]; !ok {
		t.routes[service] = make(map[uint64]Route)
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	// add new route to the table for the route destination
	if _, ok := t.routes[service][sum]; !ok {
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	return ErrDuplicateRoute
}

// Delete deletes the route from the routing table
func (t *table) Delete(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	if _, ok := t.routes[service]; !ok {
		return ErrRouteNotFound
	}

	delete(t.routes[service], sum)
	go t.sendEvent(&Event{Type: Delete, Timestamp: time.Now(), Route: r})

	return nil
}

// Update updates routing table with the new route
func (t *table) Update(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	// check if the route destination has any routes in the table
	if _, ok := t.routes[service]; !ok {
		t.routes[service] = make(map[uint64]Route)
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	t.routes[service][sum] = r
	go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r})

	return nil
}

// List returns a list of all routes in the table
func (t *table) List() ([]Route, error) {
	t.RLock()
	defer t.RUnlock()

	var routes []Route
	for _, rmap := range t.routes {
		for _, route := range rmap {
			routes = append(routes, route)
		}
	}

	return routes, nil
}

// isMatch checks if the route matches given query options
func isMatch(route Route, gateway, network, router string) bool {
	if gateway == "*" || gateway == route.Gateway {
		if network == "*" || network == route.Network {
			if router == "*" || router == route.Router {
				return true
			}
		}
	}
	return false
}

// findRoutes finds all the routes for given network and router and returns them
func findRoutes(routes map[uint64]Route, gateway, network, router string) []Route {
	var results []Route
	for _, route := range routes {
		if isMatch(route, gateway, network, router) {
			results = append(results, route)
		}
	}
	return results
}

// Lookup queries routing table and returns all routes that match the lookup query
func (t *table) Query(q Query) ([]Route, error) {
	t.RLock()
	defer t.RUnlock()

	if q.Options().Service != "*" {
		if _, ok := t.routes[q.Options().Service]; !ok {
			return nil, ErrRouteNotFound
		}
		return findRoutes(t.routes[q.Options().Service], q.Options().Gateway, q.Options().Network, q.Options().Router), nil
	}

	var results []Route
	// search through all destinations
	for _, routes := range t.routes {
		results = append(results, findRoutes(routes, q.Options().Gateway, q.Options().Network, q.Options().Router)...)
	}

	return results, nil
}

// Watch returns routing table entry watcher
func (t *table) Watch(opts ...WatchOption) (Watcher, error) {
	// by default watch everything
	wopts := WatchOptions{
		Service: "*",
	}

	for _, o := range opts {
		o(&wopts)
	}

	w := &tableWatcher{
		id:      uuid.New().String(),
		opts:    wopts,
		resChan: make(chan *Event, 10),
		done:    make(chan struct{}),
	}

	// when the watcher is stopped delete it
	go func() {
		<-w.done
		t.Lock()
		delete(t.watchers, w.id)
		t.Unlock()
	}()

	// save the watcher
	t.Lock()
	t.watchers[w.id] = w
	t.Unlock()

	return w, nil
}
<commit_msg>Only emit event if Update actually happens<commit_after>package router

import (
	"errors"
	"sync"
	"time"

	"github.com/google/uuid"
)

var (
	// ErrRouteNotFound is returned when no route was found in the routing table
	ErrRouteNotFound = errors.New("route not found")
	// ErrDuplicateRoute is returned when the route already exists
	ErrDuplicateRoute = errors.New("duplicate route")
)

// table is an in-memory routing table
type table struct {
	sync.RWMutex
	// routes stores service routes
	routes map[string]map[uint64]Route
	// watchers stores table watchers
	watchers map[string]*tableWatcher
}

// newtable creates a new routing table and returns it
func newTable(opts ...Option) *table {
	return &table{
		routes:   make(map[string]map[uint64]Route),
		watchers: make(map[string]*tableWatcher),
	}
}

// sendEvent sends events to all subscribed watchers
func (t *table) sendEvent(e *Event) {
	t.RLock()
	defer t.RUnlock()

	for _, w := range t.watchers {
		select {
		case w.resChan <- e:
		case <-w.done:
		}
	}
}

// Create creates new route in the routing table
func (t *table) Create(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	// check if there are any routes in the table for the route destination
	if _, ok := t.routes[service]; !ok {
		t.routes[service] = make(map[uint64]Route)
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	// add new route to the table for the route destination
	if _, ok := t.routes[service][sum]; !ok {
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	return ErrDuplicateRoute
}

// Delete deletes the route from the routing table
func (t *table) Delete(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	if _, ok := t.routes[service]; !ok {
		return ErrRouteNotFound
	}

	delete(t.routes[service], sum)
	go t.sendEvent(&Event{Type: Delete, Timestamp: time.Now(), Route: r})

	return nil
}

// Update updates routing table with the new route
func (t *table) Update(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	// check if the route destination has any routes in the table
	if _, ok := t.routes[service]; !ok {
		t.routes[service] = make(map[uint64]Route)
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	if _, ok := t.routes[service][sum]; !ok {
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r})
	}

	return nil
}

// List returns a list of all routes in the table
func (t *table) List() ([]Route, error) {
	t.RLock()
	defer t.RUnlock()

	var routes []Route
	for _, rmap := range t.routes {
		for _, route := range rmap {
			routes = append(routes, route)
		}
	}

	return routes, nil
}

// isMatch checks if the route matches given query options
func isMatch(route Route, gateway, network, router string) bool {
	if gateway == "*" || gateway == route.Gateway {
		if network == "*" || network == route.Network {
			if router == "*" || router == route.Router {
				return true
			}
		}
	}
	return false
}

// findRoutes finds all the routes for given network and router and returns them
func findRoutes(routes map[uint64]Route, gateway, network, router string) []Route {
	var results []Route
	for _, route := range routes {
		if isMatch(route, gateway, network, router) {
			results = append(results, route)
		}
	}
	return results
}

// Lookup queries routing table and returns all routes that match the lookup query
func (t *table) Query(q Query) ([]Route, error) {
	t.RLock()
	defer t.RUnlock()

	if q.Options().Service != "*" {
		if _, ok := t.routes[q.Options().Service]; !ok {
			return nil, ErrRouteNotFound
		}
		return findRoutes(t.routes[q.Options().Service], q.Options().Gateway, q.Options().Network, q.Options().Router), nil
	}

	var results []Route
	// search through all destinations
	for _, routes := range t.routes {
		results = append(results, findRoutes(routes, q.Options().Gateway, q.Options().Network, q.Options().Router)...)
	}

	return results, nil
}

// Watch returns routing table entry watcher
func (t *table) Watch(opts ...WatchOption) (Watcher, error) {
	// by default watch everything
	wopts := WatchOptions{
		Service: "*",
	}

	for _, o := range opts {
		o(&wopts)
	}

	w := &tableWatcher{
		id:      uuid.New().String(),
		opts:    wopts,
		resChan: make(chan *Event, 10),
		done:    make(chan struct{}),
	}

	// when the watcher is stopped delete it
	go func() {
		<-w.done
		t.Lock()
		delete(t.watchers, w.id)
		t.Unlock()
	}()

	// save the watcher
	t.Lock()
	t.watchers[w.id] = w
	t.Unlock()

	return w, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2021 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 tester

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/octago/sflags/gen/gpflag"
	"k8s.io/klog/v2"

	"sigs.k8s.io/kubetest2/pkg/testers/ginkgo"
)

// Tester wraps kubetest2's ginkgo tester with additional functionality
type Tester struct {
	*ginkgo.Tester
}

func (t *Tester) pretestSetup() error {
	kubectlPath, err := t.AcquireKubectl()
	if err != nil {
		return fmt.Errorf("failed to get kubectl package from published releases: %s", err)
	}

	existingPath := os.Getenv("PATH")
	newPath := fmt.Sprintf("%v:%v", filepath.Dir(kubectlPath), existingPath)
	klog.Info("Setting PATH=", newPath)
	return os.Setenv("PATH", newPath)
}

func (t *Tester) execute() error {
	fs, err := gpflag.Parse(t)
	if err != nil {
		return fmt.Errorf("failed to initialize tester: %v", err)
	}

	help := fs.BoolP("help", "h", false, "")
	if err := fs.Parse(os.Args); err != nil {
		return fmt.Errorf("failed to parse flags: %v", err)
	}

	if *help {
		fs.SetOutput(os.Stdout)
		fs.PrintDefaults()
		return nil
	}

	if err := t.pretestSetup(); err != nil {
		return err
	}

	return t.Execute()
}

func NewDefaultTester() *Tester {
	return &Tester{
		ginkgo.NewDefaultTester(),
	}
}

func Main() {
	t := NewDefaultTester()
	if err := t.execute(); err != nil {
		klog.Fatalf("failed to run ginkgo tester: %v", err)
	}
}
<commit_msg>kubetest2: Add --host argument<commit_after>/*
Copyright 2021 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 tester

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/octago/sflags/gen/gpflag"
	"k8s.io/klog/v2"

	"sigs.k8s.io/kubetest2/pkg/testers/ginkgo"
)

// Tester wraps kubetest2's ginkgo tester with additional functionality
type Tester struct {
	*ginkgo.Tester
}

func (t *Tester) pretestSetup() error {
	kubectlPath, err := t.AcquireKubectl()
	if err != nil {
		return fmt.Errorf("failed to get kubectl package from published releases: %s", err)
	}

	existingPath := os.Getenv("PATH")
	newPath := fmt.Sprintf("%v:%v", filepath.Dir(kubectlPath), existingPath)
	klog.Info("Setting PATH=", newPath)
	return os.Setenv("PATH", newPath)
}

// The --host argument was required in the kubernetes e2e tests, until https://github.com/kubernetes/kubernetes/pull/87030
// We can likely drop this when we drop support / testing for k8s 1.17
func (t *Tester) addHostArgument() error {
	args := []string{
		"kubectl", "config", "view", "--minify", "-o", "jsonpath='{.clusters[0].cluster.server}'",
	}
	c := exec.Command(args[0], args[1:]...)
	var stdout bytes.Buffer
	c.Stdout = &stdout
	var stderr bytes.Buffer
	c.Stderr = &stderr
	if err := c.Run(); err != nil {
		klog.Warningf("failed to run %s; stderr=%s", strings.Join(args, " "), stderr.String())
		return fmt.Errorf("error querying current config from kubectl: %w", err)
	}

	server := strings.TrimSpace(stdout.String())
	if server == "" {
		return fmt.Errorf("kubeconfig did not contain server")
	}

	klog.Info("Adding --host=%s", server)
	t.TestArgs += " --host=" + server
	return nil
}

func (t *Tester) execute() error {
	fs, err := gpflag.Parse(t)
	if err != nil {
		return fmt.Errorf("failed to initialize tester: %v", err)
	}

	help := fs.BoolP("help", "h", false, "")
	if err := fs.Parse(os.Args); err != nil {
		return fmt.Errorf("failed to parse flags: %v", err)
	}

	if *help {
		fs.SetOutput(os.Stdout)
		fs.PrintDefaults()
		return nil
	}

	if err := t.pretestSetup(); err != nil {
		return err
	}

	if err := t.addHostArgument(); err != nil {
		return err
	}

	return t.Execute()
}

func NewDefaultTester() *Tester {
	return &Tester{
		ginkgo.NewDefaultTester(),
	}
}

func Main() {
	t := NewDefaultTester()
	if err := t.execute(); err != nil {
		klog.Fatalf("failed to run ginkgo tester: %v", 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")
	}

	return []byte("Marketer added succesfully!"), 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")

	return []byte("Account added succesfully!"), 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")

	return []byte("Assignment added succesfully!"), 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>Added test methods to check string return<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:"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")
	}

	return []byte("Marketer added succesfully!"), 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")

	return []byte("Account added succesfully!"), 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")

	return []byte("Assignment added succesfully!"), 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
}

func (t *SimpleChaincode) MyInvoke(stub shim.ChaincodeStubInterface, function string, args []string) (string, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "testaccount" {
		return t.testaccount(stub, args)
	}
	fmt.Println(" My invoke did not find func: " + function)

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

func (t *SimpleChaincode) testaccount(stub shim.ChaincodeStubInterface, args []string) (string, 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 my account to state")

	return "My Account added succesfully!", nil
}
<|endoftext|>


<commit_before>package pubsub

import (
	"context"
	"errors"
	"fmt"
	"go.uber.org/zap"
	"strings"
	"sync"

	"cloud.google.com/go/pubsub"

	"github.com/cloudevents/sdk-go/pkg/cloudevents"
	cecontext "github.com/cloudevents/sdk-go/pkg/cloudevents/context"
	"github.com/cloudevents/sdk-go/pkg/cloudevents/transport"
	"github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/internal"
)

// Transport adheres to transport.Transport.
var _ transport.Transport = (*Transport)(nil)

const (
	TransportName = "Pub/Sub"
)

type subscriptionWithTopic struct {
	topicID        string
	subscriptionID string
}

// Transport acts as both a pubsub topic and a pubsub subscription .
type Transport struct {
	// Encoding
	Encoding Encoding

	// DefaultEncodingSelectionFn allows for other encoding selection strategies to be injected.
	DefaultEncodingSelectionFn EncodingSelector

	codec transport.Codec
	// Codec Mutex
	coMu sync.Mutex

	// PubSub

	// AllowCreateTopic controls if the transport can create a topic if it does
	// not exist.
	AllowCreateTopic bool

	// AllowCreateSubscription controls if the transport can create a
	// subscription if it does not exist.
	AllowCreateSubscription bool

	projectID      string
	topicID        string
	subscriptionID string

	gccMux sync.Mutex

	subscriptions []subscriptionWithTopic
	client        *pubsub.Client

	connectionsBySubscription map[string]*internal.Connection
	connectionsByTopic        map[string]*internal.Connection

	// Receiver
	Receiver transport.Receiver

	// Converter is invoked if the incoming transport receives an undecodable
	// message.
	Converter transport.Converter
}

// New creates a new pubsub transport.
func New(ctx context.Context, opts ...Option) (*Transport, error) {
	t := &Transport{}
	if err := t.applyOptions(opts...); err != nil {
		return nil, err
	}

	if t.client == nil {
		// Auth to pubsub.
		client, err := pubsub.NewClient(ctx, t.projectID)
		if err != nil {
			return nil, err
		}
		// Success.
		t.client = client
	}

	if t.connectionsBySubscription == nil {
		t.connectionsBySubscription = make(map[string]*internal.Connection, 0)
	}

	if t.connectionsByTopic == nil {
		t.connectionsByTopic = make(map[string]*internal.Connection, 0)
	}
	return t, nil
}

func (t *Transport) applyOptions(opts ...Option) error {
	for _, fn := range opts {
		if err := fn(t); err != nil {
			return err
		}
	}
	return nil
}

func (t *Transport) loadCodec(ctx context.Context) bool {
	if t.codec == nil {
		t.coMu.Lock()
		if t.DefaultEncodingSelectionFn != nil && t.Encoding != Default {
			logger := cecontext.LoggerFrom(ctx)
			logger.Warn("transport has a DefaultEncodingSelectionFn set but Encoding is not Default. DefaultEncodingSelectionFn will be ignored.")

			t.codec = &Codec{
				Encoding: t.Encoding,
			}
		} else {
			t.codec = &Codec{
				Encoding:                   t.Encoding,
				DefaultEncodingSelectionFn: t.DefaultEncodingSelectionFn,
			}
		}
		t.coMu.Unlock()
	}
	return true
}

func (t *Transport) getConnection(ctx context.Context, topic, subscription string) *internal.Connection {
	if subscription != "" {
		if conn, ok := t.connectionsBySubscription[subscription]; ok {
			return conn
		}
	}
	if topic != "" {
		if conn, ok := t.connectionsByTopic[topic]; ok {
			return conn
		}
	}

	return nil
}

func (t *Transport) getOrCreateConnection(ctx context.Context, topic, subscription string) *internal.Connection {
	t.gccMux.Lock()
	defer t.gccMux.Unlock()

	// Get.
	if conn := t.getConnection(ctx, topic, subscription); conn != nil {
		return conn
	}
	// Create.
	conn := &internal.Connection{
		AllowCreateSubscription: t.AllowCreateSubscription,
		AllowCreateTopic:        t.AllowCreateTopic,
		Client:                  t.client,
		ProjectID:               t.projectID,
		TopicID:                 topic,
		SubscriptionID:          subscription,
	}
	// Save for later.
	if subscription != "" {
		t.connectionsBySubscription[subscription] = conn
	}
	if topic != "" {
		t.connectionsByTopic[topic] = conn
	}

	return conn
}

// Send implements Transport.Send
func (t *Transport) Send(ctx context.Context, event cloudevents.Event) (context.Context, *cloudevents.Event, error) {
	// TODO populate response context properly.
	if ok := t.loadCodec(ctx); !ok {
		return ctx, nil, fmt.Errorf("unknown encoding set on transport: %d", t.Encoding)
	}

	topic := cecontext.TopicFrom(ctx)
	if topic == "" {
		topic = t.topicID
	}

	conn := t.getOrCreateConnection(ctx, topic, "")

	msg, err := t.codec.Encode(ctx, event)
	if err != nil {
		return ctx, nil, err
	}

	if m, ok := msg.(*Message); ok {
		respEvent, err := conn.Publish(ctx, &pubsub.Message{
			Attributes: m.Attributes,
			Data:       m.Data,
		})
		return ctx, respEvent, err
	}

	return ctx, nil, fmt.Errorf("failed to encode Event into a Message")
}

// SetReceiver implements Transport.SetReceiver
func (t *Transport) SetReceiver(r transport.Receiver) {
	t.Receiver = r
}

// SetConverter implements Transport.SetConverter
func (t *Transport) SetConverter(c transport.Converter) {
	t.Converter = c
}

// HasConverter implements Transport.HasConverter
func (t *Transport) HasConverter() bool {
	return t.Converter != nil
}

func (t *Transport) startSubscriber(ctx context.Context, sub subscriptionWithTopic, done func(error)) {
	logger := cecontext.LoggerFrom(ctx)
	logger.Infof("starting subscriber for Topic %q, Subscription %q", sub.topicID, sub.subscriptionID)
	conn := t.getOrCreateConnection(ctx, sub.topicID, sub.subscriptionID)

	logger.Info("conn is", conn)
	if conn == nil {
		err := fmt.Errorf("failed to find connection for Topic: %q, Subscription: %q", sub.topicID, sub.subscriptionID)
		done(err)
		return
	}
	// Ok, ready to start pulling.
	err := conn.Receive(ctx, func(ctx context.Context, m *pubsub.Message) {
		logger.Info("got an event!")
		msg := &Message{
			Attributes: m.Attributes,
			Data:       m.Data,
		}
		event, err := t.codec.Decode(ctx, msg)
		// If codec returns and error, try with the converter if it is set.
		if err != nil && t.HasConverter() {
			event, err = t.Converter.Convert(ctx, msg, err)
		}
		if err != nil {
			logger.Errorw("failed to decode message", zap.Error(err))
			m.Nack()
			return
		}

		if err := t.Receiver.Receive(ctx, *event, nil); err != nil {
			logger.Warnw("pubsub receiver return err", zap.Error(err))
			m.Nack()
			return
		}
		m.Ack()
	})
	done(err)
}

// StartReceiver implements Transport.StartReceiver
// NOTE: This is a blocking call.
func (t *Transport) StartReceiver(ctx context.Context) error {
	// Load the codec.
	if ok := t.loadCodec(ctx); !ok {
		return fmt.Errorf("unknown encoding set on transport: %d", t.Encoding)
	}

	cctx, cancel := context.WithCancel(ctx)
	n := len(t.subscriptions)

	// Make the channels for quit and errors.
	quit := make(chan struct{}, n)
	errc := make(chan error, n)

	// Start up each subscription.
	for _, sub := range t.subscriptions {
		go t.startSubscriber(cctx, sub, func(err error) {
			if err != nil {
				errc <- err
			} else {
				quit <- struct{}{}
			}
		})
	}

	// Block for parent context to finish.
	<-ctx.Done()
	cancel()

	// Collect errors and done calls until we have n of them.
	errs := []string(nil)
	for success := 0; success < n; success++ {
		var err error
		select {
		case err = <-errc:
		case <-quit:
		}
		if err != nil {
			errs = append(errs, err.Error())
		}
	}
	close(quit)
	close(errc)

	return errors.New(strings.Join(errs, "\n"))
}
<commit_msg>Propagate pubsub subscriber errors (#185)<commit_after>package pubsub

import (
	"context"
	"errors"
	"fmt"
	"go.uber.org/zap"
	"strings"
	"sync"

	"cloud.google.com/go/pubsub"

	"github.com/cloudevents/sdk-go/pkg/cloudevents"
	cecontext "github.com/cloudevents/sdk-go/pkg/cloudevents/context"
	"github.com/cloudevents/sdk-go/pkg/cloudevents/transport"
	"github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/internal"
)

// Transport adheres to transport.Transport.
var _ transport.Transport = (*Transport)(nil)

const (
	TransportName = "Pub/Sub"
)

type subscriptionWithTopic struct {
	topicID        string
	subscriptionID string
}

// Transport acts as both a pubsub topic and a pubsub subscription .
type Transport struct {
	// Encoding
	Encoding Encoding

	// DefaultEncodingSelectionFn allows for other encoding selection strategies to be injected.
	DefaultEncodingSelectionFn EncodingSelector

	codec transport.Codec
	// Codec Mutex
	coMu sync.Mutex

	// PubSub

	// AllowCreateTopic controls if the transport can create a topic if it does
	// not exist.
	AllowCreateTopic bool

	// AllowCreateSubscription controls if the transport can create a
	// subscription if it does not exist.
	AllowCreateSubscription bool

	projectID      string
	topicID        string
	subscriptionID string

	gccMux sync.Mutex

	subscriptions []subscriptionWithTopic
	client        *pubsub.Client

	connectionsBySubscription map[string]*internal.Connection
	connectionsByTopic        map[string]*internal.Connection

	// Receiver
	Receiver transport.Receiver

	// Converter is invoked if the incoming transport receives an undecodable
	// message.
	Converter transport.Converter
}

// New creates a new pubsub transport.
func New(ctx context.Context, opts ...Option) (*Transport, error) {
	t := &Transport{}
	if err := t.applyOptions(opts...); err != nil {
		return nil, err
	}

	if t.client == nil {
		// Auth to pubsub.
		client, err := pubsub.NewClient(ctx, t.projectID)
		if err != nil {
			return nil, err
		}
		// Success.
		t.client = client
	}

	if t.connectionsBySubscription == nil {
		t.connectionsBySubscription = make(map[string]*internal.Connection, 0)
	}

	if t.connectionsByTopic == nil {
		t.connectionsByTopic = make(map[string]*internal.Connection, 0)
	}
	return t, nil
}

func (t *Transport) applyOptions(opts ...Option) error {
	for _, fn := range opts {
		if err := fn(t); err != nil {
			return err
		}
	}
	return nil
}

func (t *Transport) loadCodec(ctx context.Context) bool {
	if t.codec == nil {
		t.coMu.Lock()
		if t.DefaultEncodingSelectionFn != nil && t.Encoding != Default {
			logger := cecontext.LoggerFrom(ctx)
			logger.Warn("transport has a DefaultEncodingSelectionFn set but Encoding is not Default. DefaultEncodingSelectionFn will be ignored.")

			t.codec = &Codec{
				Encoding: t.Encoding,
			}
		} else {
			t.codec = &Codec{
				Encoding:                   t.Encoding,
				DefaultEncodingSelectionFn: t.DefaultEncodingSelectionFn,
			}
		}
		t.coMu.Unlock()
	}
	return true
}

func (t *Transport) getConnection(ctx context.Context, topic, subscription string) *internal.Connection {
	if subscription != "" {
		if conn, ok := t.connectionsBySubscription[subscription]; ok {
			return conn
		}
	}
	if topic != "" {
		if conn, ok := t.connectionsByTopic[topic]; ok {
			return conn
		}
	}

	return nil
}

func (t *Transport) getOrCreateConnection(ctx context.Context, topic, subscription string) *internal.Connection {
	t.gccMux.Lock()
	defer t.gccMux.Unlock()

	// Get.
	if conn := t.getConnection(ctx, topic, subscription); conn != nil {
		return conn
	}
	// Create.
	conn := &internal.Connection{
		AllowCreateSubscription: t.AllowCreateSubscription,
		AllowCreateTopic:        t.AllowCreateTopic,
		Client:                  t.client,
		ProjectID:               t.projectID,
		TopicID:                 topic,
		SubscriptionID:          subscription,
	}
	// Save for later.
	if subscription != "" {
		t.connectionsBySubscription[subscription] = conn
	}
	if topic != "" {
		t.connectionsByTopic[topic] = conn
	}

	return conn
}

// Send implements Transport.Send
func (t *Transport) Send(ctx context.Context, event cloudevents.Event) (context.Context, *cloudevents.Event, error) {
	// TODO populate response context properly.
	if ok := t.loadCodec(ctx); !ok {
		return ctx, nil, fmt.Errorf("unknown encoding set on transport: %d", t.Encoding)
	}

	topic := cecontext.TopicFrom(ctx)
	if topic == "" {
		topic = t.topicID
	}

	conn := t.getOrCreateConnection(ctx, topic, "")

	msg, err := t.codec.Encode(ctx, event)
	if err != nil {
		return ctx, nil, err
	}

	if m, ok := msg.(*Message); ok {
		respEvent, err := conn.Publish(ctx, &pubsub.Message{
			Attributes: m.Attributes,
			Data:       m.Data,
		})
		return ctx, respEvent, err
	}

	return ctx, nil, fmt.Errorf("failed to encode Event into a Message")
}

// SetReceiver implements Transport.SetReceiver
func (t *Transport) SetReceiver(r transport.Receiver) {
	t.Receiver = r
}

// SetConverter implements Transport.SetConverter
func (t *Transport) SetConverter(c transport.Converter) {
	t.Converter = c
}

// HasConverter implements Transport.HasConverter
func (t *Transport) HasConverter() bool {
	return t.Converter != nil
}

func (t *Transport) startSubscriber(ctx context.Context, sub subscriptionWithTopic, done func(error)) {
	logger := cecontext.LoggerFrom(ctx)
	logger.Infof("starting subscriber for Topic %q, Subscription %q", sub.topicID, sub.subscriptionID)
	conn := t.getOrCreateConnection(ctx, sub.topicID, sub.subscriptionID)

	logger.Info("conn is", conn)
	if conn == nil {
		err := fmt.Errorf("failed to find connection for Topic: %q, Subscription: %q", sub.topicID, sub.subscriptionID)
		done(err)
		return
	}
	// Ok, ready to start pulling.
	err := conn.Receive(ctx, func(ctx context.Context, m *pubsub.Message) {
		logger.Info("got an event!")
		msg := &Message{
			Attributes: m.Attributes,
			Data:       m.Data,
		}
		event, err := t.codec.Decode(ctx, msg)
		// If codec returns and error, try with the converter if it is set.
		if err != nil && t.HasConverter() {
			event, err = t.Converter.Convert(ctx, msg, err)
		}
		if err != nil {
			logger.Errorw("failed to decode message", zap.Error(err))
			m.Nack()
			return
		}

		if err := t.Receiver.Receive(ctx, *event, nil); err != nil {
			logger.Warnw("pubsub receiver return err", zap.Error(err))
			m.Nack()
			return
		}
		m.Ack()
	})
	done(err)
}

// StartReceiver implements Transport.StartReceiver
// NOTE: This is a blocking call.
func (t *Transport) StartReceiver(ctx context.Context) error {
	// Load the codec.
	if ok := t.loadCodec(ctx); !ok {
		return fmt.Errorf("unknown encoding set on transport: %d", t.Encoding)
	}

	cctx, cancel := context.WithCancel(ctx)
	defer cancel()
	n := len(t.subscriptions)

	// Make the channels for quit and errors.
	quit := make(chan struct{}, n)
	errc := make(chan error, n)

	// Start up each subscription.
	for _, sub := range t.subscriptions {
		go t.startSubscriber(cctx, sub, func(err error) {
			if err != nil {
				errc <- err
			} else {
				quit <- struct{}{}
			}
		})
	}

	// Collect errors and done calls until we have n of them.
	errs := []string(nil)
	for success := 0; success < n; success++ {
		var err error
		select {
		case <-ctx.Done(): // Block for parent context to finish.
			success--
		case err = <-errc: // Collect errors
		case <-quit:
		}
		if cancel != nil {
			// Stop all other subscriptions.
			cancel()
			cancel = nil
		}
		if err != nil {
			errs = append(errs, err.Error())
		}
	}

	close(quit)
	close(errc)

	return errors.New(strings.Join(errs, "\n"))
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 gce

import (
	"fmt"
	"net/http"
	"path"

	"k8s.io/apimachinery/pkg/types"
	"k8s.io/kubernetes/pkg/cloudprovider"

	"github.com/golang/glog"
	compute "google.golang.org/api/compute/v1"
)

func newRoutesMetricContext(request string) *metricContext {
	return newGenericMetricContext("routes", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
}

func (gce *GCECloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) {
	var routes []*cloudprovider.Route
	pageToken := ""
	page := 0
	for ; page == 0 || (pageToken != "" && page < maxPages); page++ {
		mc := newRoutesMetricContext("list_page")
		listCall := gce.service.Routes.List(gce.NetworkProjectID())

		prefix := truncateClusterName(clusterName)
		// Filter for routes starting with clustername AND belonging to the
		// relevant gcp network AND having description = "k8s-node-route".
		filter := "(name eq " + prefix + "-.*) "
		filter = filter + "(network eq " + gce.NetworkURL() + ") "
		filter = filter + "(description eq " + k8sNodeRouteTag + ")"
		listCall = listCall.Filter(filter)
		if pageToken != "" {
			listCall = listCall.PageToken(pageToken)
		}
		res, err := listCall.Do()
		mc.Observe(err)
		if err != nil {
			glog.Errorf("Error getting routes from GCE: %v", err)
			return nil, err
		}
		pageToken = res.NextPageToken
		for _, r := range res.Items {
			target := path.Base(r.NextHopInstance)
			// TODO: Should we lastComponent(target) this?
			targetNodeName := types.NodeName(target) // NodeName == Instance Name on GCE
			routes = append(routes, &cloudprovider.Route{Name: r.Name, TargetNode: targetNodeName, DestinationCIDR: r.DestRange})
		}
	}
	if page >= maxPages {
		glog.Errorf("ListRoutes exceeded maxPages=%d for Routes.List; truncating.", maxPages)
	}
	return routes, nil
}

func (gce *GCECloud) CreateRoute(clusterName string, nameHint string, route *cloudprovider.Route) error {
	routeName := truncateClusterName(clusterName) + "-" + nameHint

	instanceName := mapNodeNameToInstanceName(route.TargetNode)
	targetInstance, err := gce.getInstanceByName(instanceName)
	if err != nil {
		return err
	}

	mc := newRoutesMetricContext("create")
	insertOp, err := gce.service.Routes.Insert(gce.NetworkProjectID(), &compute.Route{
		Name:            routeName,
		DestRange:       route.DestinationCIDR,
		NextHopInstance: fmt.Sprintf("zones/%s/instances/%s", targetInstance.Zone, targetInstance.Name),
		Network:         gce.NetworkURL(),
		Priority:        1000,
		Description:     k8sNodeRouteTag,
	}).Do()
	if err != nil {
		if isHTTPErrorCode(err, http.StatusConflict) {
			glog.Infof("Route %v already exists.", routeName)
			return nil
		} else {
			return mc.Observe(err)
		}
	}
	return gce.waitForGlobalOpInProject(insertOp, gce.NetworkProjectID(), mc)
}

func (gce *GCECloud) DeleteRoute(clusterName string, route *cloudprovider.Route) error {
	mc := newRoutesMetricContext("delete")
	deleteOp, err := gce.service.Routes.Delete(gce.NetworkProjectID(), route.Name).Do()
	if err != nil {
		return mc.Observe(err)
	}
	return gce.waitForGlobalOpInProject(deleteOp, gce.NetworkProjectID(), mc)
}

func truncateClusterName(clusterName string) string {
	if len(clusterName) > 26 {
		return clusterName[:26]
	}
	return clusterName
}
<commit_msg>Update Routes to use generated code<commit_after>/*
Copyright 2017 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 gce

import (
	"context"
	"fmt"
	"net/http"
	"path"

	"github.com/golang/glog"
	compute "google.golang.org/api/compute/v1"
	"k8s.io/apimachinery/pkg/types"

	"k8s.io/kubernetes/pkg/cloudprovider"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
	"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
)

func newRoutesMetricContext(request string) *metricContext {
	return newGenericMetricContext("routes", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
}

// ListRoutes in the cloud environment.
func (gce *GCECloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) {
	mc := newRoutesMetricContext("list")
	prefix := truncateClusterName(clusterName)
	f := filter.Regexp("name", prefix+"-.*").AndRegexp("network", gce.NetworkURL()).AndRegexp("description", k8sNodeRouteTag)
	routes, err := gce.c.Routes().List(context.Background(), f)
	if err != nil {
		return nil, mc.Observe(err)
	}
	var croutes []*cloudprovider.Route
	for _, r := range routes {
		target := path.Base(r.NextHopInstance)
		// TODO: Should we lastComponent(target) this?
		targetNodeName := types.NodeName(target) // NodeName == Instance Name on GCE
		croutes = append(croutes, &cloudprovider.Route{
			Name:            r.Name,
			TargetNode:      targetNodeName,
			DestinationCIDR: r.DestRange,
		})
	}
	return croutes, mc.Observe(nil)
}

// CreateRoute in the cloud environment.
func (gce *GCECloud) CreateRoute(clusterName string, nameHint string, route *cloudprovider.Route) error {
	mc := newRoutesMetricContext("create")

	targetInstance, err := gce.getInstanceByName(mapNodeNameToInstanceName(route.TargetNode))
	if err != nil {
		return mc.Observe(err)
	}
	cr := &compute.Route{
		Name:            truncateClusterName(clusterName) + "-" + nameHint,
		DestRange:       route.DestinationCIDR,
		NextHopInstance: fmt.Sprintf("zones/%s/instances/%s", targetInstance.Zone, targetInstance.Name),
		Network:         gce.NetworkURL(),
		Priority:        1000,
		Description:     k8sNodeRouteTag,
	}
	err = gce.c.Routes().Insert(context.Background(), meta.GlobalKey(cr.Name), cr)
	if isHTTPErrorCode(err, http.StatusConflict) {
		glog.Infof("Route %q already exists.", cr.Name)
		err = nil
	}
	return mc.Observe(err)
}

// DeleteRoute from the cloud environment.
func (gce *GCECloud) DeleteRoute(clusterName string, route *cloudprovider.Route) error {
	mc := newRoutesMetricContext("delete")
	return mc.Observe(gce.c.Routes().Delete(context.Background(), meta.GlobalKey(route.Name)))
}

func truncateClusterName(clusterName string) string {
	if len(clusterName) > 26 {
		return clusterName[:26]
	}
	return clusterName
}
<|endoftext|>


<commit_before>package migrations

import (
	. "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
	"github.com/grafana/grafana/pkg/setting"
)

func addAlertMigrations(mg *Migrator) {
	if !setting.AlertingEnabled {
		return
	}

	alertV1 := Table{
		Name: "alert_rule",
		Columns: []*Column{
			{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
			{Name: "dashboard_id", Type: DB_BigInt, Nullable: false},
			{Name: "panel_id", Type: DB_BigInt, Nullable: false},
			{Name: "org_id", Type: DB_BigInt, Nullable: false},
			{Name: "query", Type: DB_Text, Nullable: false},
			{Name: "query_ref_id", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "warn_level", Type: DB_BigInt, Nullable: false},
			{Name: "warn_operator", Type: DB_NVarchar, Length: 10, Nullable: false},
			{Name: "crit_level", Type: DB_BigInt, Nullable: false},
			{Name: "crit_operator", Type: DB_NVarchar, Length: 10, Nullable: false},
			{Name: "interval", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "title", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "description", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "query_range", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "aggregator", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "state", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "created", Type: DB_DateTime, Nullable: false},
			{Name: "updated", Type: DB_DateTime, Nullable: false},
		},
	}

	// create table
	mg.AddMigration("create alert_rule table v1", NewAddTableMigration(alertV1))

	alert_changes := Table{
		Name: "alert_rule_change",
		Columns: []*Column{
			{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
			{Name: "alert_id", Type: DB_BigInt, Nullable: false},
			{Name: "org_id", Type: DB_BigInt, Nullable: false},
			{Name: "type", Type: DB_NVarchar, Length: 50, Nullable: false},
			{Name: "created", Type: DB_DateTime, Nullable: false},
		},
	}

	mg.AddMigration("create alert_rules_updates table v1", NewAddTableMigration(alert_changes))

	alert_state_log := Table{
		Name: "alert_state",
		Columns: []*Column{
			{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
			{Name: "alert_id", Type: DB_BigInt, Nullable: false},
			{Name: "org_id", Type: DB_BigInt, Nullable: false},
			{Name: "new_state", Type: DB_NVarchar, Length: 50, Nullable: false},
			{Name: "info", Type: DB_Text, Nullable: true},
			{Name: "created", Type: DB_DateTime, Nullable: false},
		},
	}

	mg.AddMigration("create alert_state_log table v1", NewAddTableMigration(alert_state_log))
}
<commit_msg>tech(alerting): disable feature toggle<commit_after>package migrations

import (
	. "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
)

func addAlertMigrations(mg *Migrator) {
	alertV1 := Table{
		Name: "alert_rule",
		Columns: []*Column{
			{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
			{Name: "dashboard_id", Type: DB_BigInt, Nullable: false},
			{Name: "panel_id", Type: DB_BigInt, Nullable: false},
			{Name: "org_id", Type: DB_BigInt, Nullable: false},
			{Name: "query", Type: DB_Text, Nullable: false},
			{Name: "query_ref_id", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "warn_level", Type: DB_BigInt, Nullable: false},
			{Name: "warn_operator", Type: DB_NVarchar, Length: 10, Nullable: false},
			{Name: "crit_level", Type: DB_BigInt, Nullable: false},
			{Name: "crit_operator", Type: DB_NVarchar, Length: 10, Nullable: false},
			{Name: "interval", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "title", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "description", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "query_range", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "aggregator", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "state", Type: DB_NVarchar, Length: 255, Nullable: false},
			{Name: "created", Type: DB_DateTime, Nullable: false},
			{Name: "updated", Type: DB_DateTime, Nullable: false},
		},
	}

	// create table
	mg.AddMigration("create alert_rule table v1", NewAddTableMigration(alertV1))

	alert_changes := Table{
		Name: "alert_rule_change",
		Columns: []*Column{
			{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
			{Name: "alert_id", Type: DB_BigInt, Nullable: false},
			{Name: "org_id", Type: DB_BigInt, Nullable: false},
			{Name: "type", Type: DB_NVarchar, Length: 50, Nullable: false},
			{Name: "created", Type: DB_DateTime, Nullable: false},
		},
	}

	mg.AddMigration("create alert_rules_updates table v1", NewAddTableMigration(alert_changes))

	alert_state_log := Table{
		Name: "alert_state",
		Columns: []*Column{
			{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
			{Name: "alert_id", Type: DB_BigInt, Nullable: false},
			{Name: "org_id", Type: DB_BigInt, Nullable: false},
			{Name: "new_state", Type: DB_NVarchar, Length: 50, Nullable: false},
			{Name: "info", Type: DB_Text, Nullable: true},
			{Name: "created", Type: DB_DateTime, Nullable: false},
		},
	}

	mg.AddMigration("create alert_state_log table v1", NewAddTableMigration(alert_state_log))
}
<|endoftext|>


<commit_before>// Copyright 2019 Istio 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 ingress

import (
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"istio.io/istio/pkg/test"
	"istio.io/istio/pkg/test/framework/components/environment/kube"
	"istio.io/istio/pkg/test/framework/resource"
	"istio.io/istio/pkg/test/scopes"
	"istio.io/istio/pkg/test/util/retry"
)

const (
	serviceName           = "istio-ingressgateway"
	istioLabel            = "ingressgateway"
	DefaultRequestTimeout = 1 * time.Minute

	proxyContainerName = "istio-proxy"
	proxyAdminPort     = 15000
)

var (
	retryTimeout = retry.Timeout(3 * time.Minute)
	retryDelay   = retry.Delay(5 * time.Second)

	_ Instance = &kubeComponent{}
)

type kubeComponent struct {
	id        resource.ID
	namespace string
	env       *kube.Environment
}

// getHTTPAddressInner returns the ingress gateway address for plain text http requests.
func getHTTPAddressInner(env *kube.Environment, ns string) (interface{}, bool, error) {
	// In Minikube, we don't have the ingress gateway. Instead we do a little bit of trickery to to get the Node
	// port.
	if env.Settings().Minikube {
		pods, err := env.GetPods(ns, fmt.Sprintf("istio=%s", istioLabel))
		if err != nil {
			return nil, false, err
		}

		scopes.Framework.Debugf("Querying ingress, pods:\n%v\n", pods)
		if len(pods) == 0 {
			return nil, false, fmt.Errorf("no ingress pod found")
		}

		scopes.Framework.Debugf("Found pod: \n%v\n", pods[0])
		ip := pods[0].Status.HostIP
		if ip == "" {
			return nil, false, fmt.Errorf("no Host IP available on the ingress node yet")
		}

		svc, err := env.Accessor.GetService(ns, serviceName)
		if err != nil {
			return nil, false, err
		}

		scopes.Framework.Debugf("Found service for the gateway:\n%v\n", svc)
		if len(svc.Spec.Ports) == 0 {
			return nil, false, fmt.Errorf("no ports found in service: %s/%s", ns, "istio-ingressgateway")
		}

		var nodePort int32
		for _, svcPort := range svc.Spec.Ports {
			if svcPort.Protocol == "TCP" && svcPort.Port == 80 {
				nodePort = svcPort.NodePort
				break
			}
		}
		if nodePort == 0 {
			return nil, false, fmt.Errorf("no port 80 found in service: %s/%s", ns, "istio-ingressgateway")
		}

		return net.TCPAddr{IP: net.ParseIP(ip), Port: int(nodePort)}, true, nil
	}

	// Otherwise, get the load balancer IP.
	svc, err := env.Accessor.GetService(ns, serviceName)
	if err != nil {
		return nil, false, err
	}

	if len(svc.Status.LoadBalancer.Ingress) == 0 || svc.Status.LoadBalancer.Ingress[0].IP == "" {
		return nil, false, fmt.Errorf("service ingress is not available yet: %s/%s", svc.Namespace, svc.Name)
	}

	ip := svc.Status.LoadBalancer.Ingress[0].IP
	return net.TCPAddr{IP: net.ParseIP(ip), Port: 80}, true, nil
}

// getHTTPSAddressInner returns the ingress gateway address for https requests.
func getHTTPSAddressInner(env *kube.Environment, ns string) (interface{}, bool, error) {
	if env.Settings().Minikube {
		pods, err := env.GetPods(ns, fmt.Sprintf("istio=%s", istioLabel))
		if err != nil {
			return nil, false, err
		}

		scopes.Framework.Debugf("Querying ingress, pods:\n%+v\n", pods)
		if len(pods) == 0 {
			return nil, false, fmt.Errorf("no ingress pod found")
		}

		scopes.Framework.Debugf("Found pod: \n%+v\n", pods[0])
		ip := pods[0].Status.HostIP
		if ip == "" {
			return nil, false, fmt.Errorf("no Host IP available on the ingress node yet")
		}

		svc, err := env.Accessor.GetService(ns, serviceName)
		if err != nil {
			return nil, false, err
		}

		scopes.Framework.Debugf("Found service for the gateway:\n%+v\n", svc)
		if len(svc.Spec.Ports) == 0 {
			return nil, false, fmt.Errorf("no ports found in service: %s/%s", ns, "istio-ingressgateway")
		}

		var nodePort int32
		for _, svcPort := range svc.Spec.Ports {
			if svcPort.Protocol == "TCP" && svcPort.Port == 443 {
				nodePort = svcPort.NodePort
				break
			}
		}
		if nodePort == 0 {
			return nil, false, fmt.Errorf("no port 80 found in service: %s/%s", ns, "istio-ingressgateway")
		}

		return net.TCPAddr{IP: net.ParseIP(ip), Port: int(nodePort)}, true, nil
	}

	svc, err := env.Accessor.GetService(ns, serviceName)
	if err != nil {
		return nil, false, err
	}

	if len(svc.Status.LoadBalancer.Ingress) == 0 || svc.Status.LoadBalancer.Ingress[0].IP == "" {
		return nil, false, fmt.Errorf("service ingress is not available yet: %s/%s", svc.Namespace, svc.Name)
	}

	ip := svc.Status.LoadBalancer.Ingress[0].IP
	return net.TCPAddr{IP: net.ParseIP(ip), Port: 443}, true, nil
}

func newKube(ctx resource.Context, cfg Config) Instance {
	c := &kubeComponent{}
	c.id = ctx.TrackResource(c)
	c.namespace = cfg.Istio.Settings().IngressNamespace
	c.env = ctx.Environment().(*kube.Environment)

	return c
}

func (c *kubeComponent) ID() resource.ID {
	return c.id
}

// HTTPAddress returns HTTP address of ingress gateway.
func (c *kubeComponent) HTTPAddress() net.TCPAddr {
	address, err := retry.Do(func() (interface{}, bool, error) {
		return getHTTPAddressInner(c.env, c.namespace)
	}, retryTimeout, retryDelay)
	if err != nil {
		return net.TCPAddr{}
	}
	return address.(net.TCPAddr)
}

// HTTPSAddress returns HTTPS IP address and port number of ingress gateway.
func (c *kubeComponent) HTTPSAddress() net.TCPAddr {
	address, err := retry.Do(func() (interface{}, bool, error) {
		return getHTTPSAddressInner(c.env, c.namespace)
	}, retryTimeout, retryDelay)
	if err != nil {
		return net.TCPAddr{}
	}
	return address.(net.TCPAddr)
}

// createClient creates a client which sends HTTP requests or HTTPS requests, depending on
// ingress type. If host is not empty, the client will resolve domain name and verify server
// cert using the host name.
func (c *kubeComponent) createClient(options CallOptions) (*http.Client, error) {
	client := &http.Client{
		Timeout: options.Timeout,
	}
	if options.CallType != PlainText {
		scopes.Framework.Debug("Prepare root cert for client")
		roots := x509.NewCertPool()
		ok := roots.AppendCertsFromPEM([]byte(options.CaCert))
		if !ok {
			return nil, fmt.Errorf("failed to parse root certificate")
		}
		tlsConfig := &tls.Config{
			RootCAs:    roots,
			ServerName: options.Host,
		}
		if options.CallType == Mtls {
			cer, err := tls.X509KeyPair([]byte(options.Cert), []byte(options.PrivateKey))
			if err != nil {
				return nil, fmt.Errorf("failed to parse private key and server cert")
			}
			tlsConfig.Certificates = []tls.Certificate{cer}
		}
		tr := &http.Transport{
			TLSClientConfig: tlsConfig,
			DialTLS: func(netw, addr string) (net.Conn, error) {
				if s := strings.Split(addr, ":"); s[0] == options.Host {
					addr = options.Address.String()
				}
				tc, err := tls.Dial(netw, addr, tlsConfig)
				if err != nil {
					scopes.Framework.Errorf("TLS dial fail: %v", err)
					return nil, err
				}
				if err := tc.Handshake(); err != nil {
					scopes.Framework.Errorf("SSL handshake fail: %v", err)
					return nil, err
				}
				return tc, nil
			}}
		client.Transport = tr
	}
	return client, nil
}

// createRequest returns a request for client to send, or nil and error if request is failed to generate.
func (c *kubeComponent) createRequest(options CallOptions) (*http.Request, error) {
	url := "http://" + options.Address.String() + options.Path
	if options.CallType != PlainText {
		url = "https://" + options.Host + ":" + strconv.Itoa(options.Address.Port) + options.Path
	}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	if options.Host != "" {
		req.Host = options.Host
	}
	if options.Headers != nil {
		req.Header = options.Headers.Clone()
	}

	scopes.Framework.Debugf("Created a request to send %v", req)
	return req, nil
}

func (c *kubeComponent) Call(options CallOptions) (CallResponse, error) {
	if err := options.sanitize(); err != nil {
		scopes.Framework.Fatalf("CallOptions sanitization failure, error %v", err)
	}
	client, err := c.createClient(options)
	if err != nil {
		scopes.Framework.Errorf("failed to create test client, error %v", err)
		return CallResponse{}, err
	}
	req, err := c.createRequest(options)
	if err != nil {
		scopes.Framework.Errorf("failed to create request, error %v", err)
		return CallResponse{}, err
	}

	resp, err := client.Do(req)
	if err != nil {
		return CallResponse{}, err
	}
	scopes.Framework.Debugf("Received response from %q: %v", req.URL, resp.StatusCode)

	defer func() { _ = resp.Body.Close() }()

	var ba []byte
	ba, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		scopes.Framework.Warnf("Unable to connect to read from %s: %v", options.Address.String(), err)
		return CallResponse{}, err
	}
	contents := string(ba)
	status := resp.StatusCode

	response := CallResponse{
		Code: status,
		Body: contents,
	}

	return response, nil
}

func (c *kubeComponent) CallOrFail(t test.Failer, options CallOptions) CallResponse {
	t.Helper()
	resp, err := c.Call(options)
	if err != nil {
		t.Fatal(err)
	}
	return resp
}

func (c *kubeComponent) ProxyStats() (map[string]int, error) {
	var stats map[string]int
	statsJSON, err := c.adminRequest("stats?format=json")
	if err != nil {
		return stats, fmt.Errorf("failed to get response from admin port: %v", err)
	}
	return c.unmarshalStats(statsJSON)
}

// adminRequest makes a call to admin port at ingress gateway proxy and returns error on request failure.
func (c *kubeComponent) adminRequest(path string) (string, error) {
	pods, err := c.env.GetPods(c.namespace, "istio=ingressgateway")
	if err != nil {
		return "", fmt.Errorf("unable to get ingress gateway stats: %v", err)
	}
	podNs, podName := pods[0].Namespace, pods[0].Name
	// Exec onto the pod and make a curl request to the admin port
	command := fmt.Sprintf("curl http://127.0.0.1:%d/%s", proxyAdminPort, path)
	return c.env.Accessor.Exec(podNs, podName, proxyContainerName, command)
}

type statEntry struct {
	Name  string `json:"name"`
	Value int    `json:"value"`
}

type stats struct {
	StatList []statEntry `json:"stats"`
}

// unmarshalStats unmarshals Envoy stats from JSON format into a map, where stats name is
// key, and stats value is value.
func (c *kubeComponent) unmarshalStats(statsJSON string) (map[string]int, error) {
	statsMap := make(map[string]int)

	var statsArray stats
	if err := json.Unmarshal([]byte(statsJSON), &statsArray); err != nil {
		return statsMap, fmt.Errorf("unable to unmarshal stats from json: %v", err)
	}

	for _, v := range statsArray.StatList {
		statsMap[v.Name] = v.Value
	}
	return statsMap, nil
}
<commit_msg>Fix broken tests (#20616)<commit_after>// Copyright 2019 Istio 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 ingress

import (
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"istio.io/istio/pkg/test"
	"istio.io/istio/pkg/test/framework/components/environment/kube"
	"istio.io/istio/pkg/test/framework/resource"
	"istio.io/istio/pkg/test/scopes"
	"istio.io/istio/pkg/test/util/retry"
)

const (
	serviceName           = "istio-ingressgateway"
	istioLabel            = "ingressgateway"
	DefaultRequestTimeout = 1 * time.Minute

	proxyContainerName = "istio-proxy"
	proxyAdminPort     = 15000
)

var (
	retryTimeout = retry.Timeout(3 * time.Minute)
	retryDelay   = retry.Delay(5 * time.Second)

	_ Instance = &kubeComponent{}
)

type kubeComponent struct {
	id        resource.ID
	namespace string
	env       *kube.Environment
}

// getHTTPAddressInner returns the ingress gateway address for plain text http requests.
func getHTTPAddressInner(env *kube.Environment, ns string) (interface{}, bool, error) {
	// In Minikube, we don't have the ingress gateway. Instead we do a little bit of trickery to to get the Node
	// port.
	if env.Settings().Minikube {
		pods, err := env.GetPods(ns, fmt.Sprintf("istio=%s", istioLabel))
		if err != nil {
			return nil, false, err
		}

		scopes.Framework.Debugf("Querying ingress, pods:\n%v\n", pods)
		if len(pods) == 0 {
			return nil, false, fmt.Errorf("no ingress pod found")
		}

		scopes.Framework.Debugf("Found pod: \n%v\n", pods[0])
		ip := pods[0].Status.HostIP
		if ip == "" {
			return nil, false, fmt.Errorf("no Host IP available on the ingress node yet")
		}

		svc, err := env.Accessor.GetService(ns, serviceName)
		if err != nil {
			return nil, false, err
		}

		scopes.Framework.Debugf("Found service for the gateway:\n%v\n", svc)
		if len(svc.Spec.Ports) == 0 {
			return nil, false, fmt.Errorf("no ports found in service: %s/%s", ns, "istio-ingressgateway")
		}

		var nodePort int32
		for _, svcPort := range svc.Spec.Ports {
			if svcPort.Protocol == "TCP" && svcPort.Port == 80 {
				nodePort = svcPort.NodePort
				break
			}
		}
		if nodePort == 0 {
			return nil, false, fmt.Errorf("no port 80 found in service: %s/%s", ns, "istio-ingressgateway")
		}

		return net.TCPAddr{IP: net.ParseIP(ip), Port: int(nodePort)}, true, nil
	}

	// Otherwise, get the load balancer IP.
	svc, err := env.Accessor.GetService(ns, serviceName)
	if err != nil {
		return nil, false, err
	}

	if len(svc.Status.LoadBalancer.Ingress) == 0 || svc.Status.LoadBalancer.Ingress[0].IP == "" {
		return nil, false, fmt.Errorf("service ingress is not available yet: %s/%s", svc.Namespace, svc.Name)
	}

	ip := svc.Status.LoadBalancer.Ingress[0].IP
	return net.TCPAddr{IP: net.ParseIP(ip), Port: 80}, true, nil
}

// getHTTPSAddressInner returns the ingress gateway address for https requests.
func getHTTPSAddressInner(env *kube.Environment, ns string) (interface{}, bool, error) {
	if env.Settings().Minikube {
		pods, err := env.GetPods(ns, fmt.Sprintf("istio=%s", istioLabel))
		if err != nil {
			return nil, false, err
		}

		scopes.Framework.Debugf("Querying ingress, pods:\n%+v\n", pods)
		if len(pods) == 0 {
			return nil, false, fmt.Errorf("no ingress pod found")
		}

		scopes.Framework.Debugf("Found pod: \n%+v\n", pods[0])
		ip := pods[0].Status.HostIP
		if ip == "" {
			return nil, false, fmt.Errorf("no Host IP available on the ingress node yet")
		}

		svc, err := env.Accessor.GetService(ns, serviceName)
		if err != nil {
			return nil, false, err
		}

		scopes.Framework.Debugf("Found service for the gateway:\n%+v\n", svc)
		if len(svc.Spec.Ports) == 0 {
			return nil, false, fmt.Errorf("no ports found in service: %s/%s", ns, "istio-ingressgateway")
		}

		var nodePort int32
		for _, svcPort := range svc.Spec.Ports {
			if svcPort.Protocol == "TCP" && svcPort.Port == 443 {
				nodePort = svcPort.NodePort
				break
			}
		}
		if nodePort == 0 {
			return nil, false, fmt.Errorf("no port 80 found in service: %s/%s", ns, "istio-ingressgateway")
		}

		return net.TCPAddr{IP: net.ParseIP(ip), Port: int(nodePort)}, true, nil
	}

	svc, err := env.Accessor.GetService(ns, serviceName)
	if err != nil {
		return nil, false, err
	}

	if len(svc.Status.LoadBalancer.Ingress) == 0 || svc.Status.LoadBalancer.Ingress[0].IP == "" {
		return nil, false, fmt.Errorf("service ingress is not available yet: %s/%s", svc.Namespace, svc.Name)
	}

	ip := svc.Status.LoadBalancer.Ingress[0].IP
	return net.TCPAddr{IP: net.ParseIP(ip), Port: 443}, true, nil
}

func newKube(ctx resource.Context, cfg Config) Instance {
	c := &kubeComponent{}
	c.id = ctx.TrackResource(c)
	c.namespace = cfg.Istio.Settings().IngressNamespace
	c.env = ctx.Environment().(*kube.Environment)

	return c
}

func (c *kubeComponent) ID() resource.ID {
	return c.id
}

// HTTPAddress returns HTTP address of ingress gateway.
func (c *kubeComponent) HTTPAddress() net.TCPAddr {
	address, err := retry.Do(func() (interface{}, bool, error) {
		return getHTTPAddressInner(c.env, c.namespace)
	}, retryTimeout, retryDelay)
	if err != nil {
		return net.TCPAddr{}
	}
	return address.(net.TCPAddr)
}

// HTTPSAddress returns HTTPS IP address and port number of ingress gateway.
func (c *kubeComponent) HTTPSAddress() net.TCPAddr {
	address, err := retry.Do(func() (interface{}, bool, error) {
		return getHTTPSAddressInner(c.env, c.namespace)
	}, retryTimeout, retryDelay)
	if err != nil {
		return net.TCPAddr{}
	}
	return address.(net.TCPAddr)
}

// createClient creates a client which sends HTTP requests or HTTPS requests, depending on
// ingress type. If host is not empty, the client will resolve domain name and verify server
// cert using the host name.
func (c *kubeComponent) createClient(options CallOptions) (*http.Client, error) {
	client := &http.Client{
		Timeout: options.Timeout,
	}
	if options.CallType != PlainText {
		scopes.Framework.Debug("Prepare root cert for client")
		roots := x509.NewCertPool()
		ok := roots.AppendCertsFromPEM([]byte(options.CaCert))
		if !ok {
			return nil, fmt.Errorf("failed to parse root certificate")
		}
		tlsConfig := &tls.Config{
			RootCAs:    roots,
			ServerName: options.Host,
		}
		if options.CallType == Mtls {
			cer, err := tls.X509KeyPair([]byte(options.Cert), []byte(options.PrivateKey))
			if err != nil {
				return nil, fmt.Errorf("failed to parse private key and server cert")
			}
			tlsConfig.Certificates = []tls.Certificate{cer}
		}
		tr := &http.Transport{
			TLSClientConfig: tlsConfig,
			DialTLS: func(netw, addr string) (net.Conn, error) {
				if s := strings.Split(addr, ":"); s[0] == options.Host {
					addr = options.Address.String()
				}
				tc, err := tls.Dial(netw, addr, tlsConfig)
				if err != nil {
					scopes.Framework.Errorf("TLS dial fail: %v", err)
					return nil, err
				}
				if err := tc.Handshake(); err != nil {
					scopes.Framework.Errorf("SSL handshake fail: %v", err)
					return nil, err
				}
				return tc, nil
			}}
		client.Transport = tr
	}
	return client, nil
}

// createRequest returns a request for client to send, or nil and error if request is failed to generate.
func (c *kubeComponent) createRequest(options CallOptions) (*http.Request, error) {
	url := "http://" + options.Address.String() + options.Path
	if options.CallType != PlainText {
		url = "https://" + options.Host + ":" + strconv.Itoa(options.Address.Port) + options.Path
	}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	if options.Host != "" {
		req.Host = options.Host
	}
	if options.Headers != nil {
		req.Header = options.Headers.Clone()
	}

	scopes.Framework.Debugf("Created a request to send %v", req)
	return req, nil
}

func (c *kubeComponent) Call(options CallOptions) (CallResponse, error) {
	if err := options.sanitize(); err != nil {
		scopes.Framework.Fatalf("CallOptions sanitization failure, error %v", err)
	}
	client, err := c.createClient(options)
	if err != nil {
		scopes.Framework.Errorf("failed to create test client, error %v", err)
		return CallResponse{}, err
	}
	req, err := c.createRequest(options)
	if err != nil {
		scopes.Framework.Errorf("failed to create request, error %v", err)
		return CallResponse{}, err
	}

	resp, err := client.Do(req)
	if err != nil {
		return CallResponse{}, err
	}
	scopes.Framework.Debugf("Received response from %q: %v", req.URL, resp.StatusCode)

	defer func() { _ = resp.Body.Close() }()

	var ba []byte
	ba, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		scopes.Framework.Warnf("Unable to connect to read from %s: %v", options.Address.String(), err)
		return CallResponse{}, err
	}
	contents := string(ba)
	status := resp.StatusCode

	response := CallResponse{
		Code: status,
		Body: contents,
	}

	return response, nil
}

func (c *kubeComponent) CallOrFail(t test.Failer, options CallOptions) CallResponse {
	t.Helper()
	resp, err := c.Call(options)
	if err != nil {
		t.Fatal(err)
	}
	return resp
}

func (c *kubeComponent) ProxyStats() (map[string]int, error) {
	var stats map[string]int
	statsJSON, err := c.adminRequest("stats?format=json")
	if err != nil {
		return stats, fmt.Errorf("failed to get response from admin port: %v", err)
	}
	return c.unmarshalStats(statsJSON)
}

// adminRequest makes a call to admin port at ingress gateway proxy and returns error on request failure.
func (c *kubeComponent) adminRequest(path string) (string, error) {
	pods, err := c.env.GetPods(c.namespace, "istio=ingressgateway")
	if err != nil {
		return "", fmt.Errorf("unable to get ingress gateway stats: %v", err)
	}
	podNs, podName := pods[0].Namespace, pods[0].Name
	// Exec onto the pod and make a curl request to the admin port
	command := fmt.Sprintf("curl http://127.0.0.1:%d/%s", proxyAdminPort, path)
	return c.env.Accessor.Exec(podNs, podName, proxyContainerName, command)
}

type statEntry struct {
	Name  string      `json:"name"`
	Value json.Number `json:"value"`
}

type stats struct {
	StatList []statEntry `json:"stats"`
}

// unmarshalStats unmarshals Envoy stats from JSON format into a map, where stats name is
// key, and stats value is value.
func (c *kubeComponent) unmarshalStats(statsJSON string) (map[string]int, error) {
	statsMap := make(map[string]int)

	var statsArray stats
	if err := json.Unmarshal([]byte(statsJSON), &statsArray); err != nil {
		return statsMap, fmt.Errorf("unable to unmarshal stats from json: %v", err)
	}

	for _, v := range statsArray.StatList {
		if v.Value == "" {
			continue
		}
		tmp, _ := v.Value.Float64()
		statsMap[v.Name] = int(tmp)
	}
	return statsMap, nil
}
<|endoftext|>


<commit_before>package pfs

import (
	"fmt"
	"regexp"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/pachyderm/pachyderm/src/client/pkg/grpcutil"
)

// ErrFileNotFound represents a file-not-found error.
type ErrFileNotFound struct {
	File *pfs.File
}

// ErrRepoNotFound represents a repo-not-found error.
type ErrRepoNotFound struct {
	Repo *pfs.Repo
}

// ErrRepoExists represents a repo-exists error.
type ErrRepoExists struct {
	Repo *pfs.Repo
}

// ErrCommitNotFound represents a commit-not-found error.
type ErrCommitNotFound struct {
	Commit *pfs.Commit
}

// ErrNoHead represents an error encountered because a branch has no head (e.g.
// inspectCommit(master) when 'master' has no commits)
type ErrNoHead struct {
	Branch *pfs.Branch
}

// ErrCommitExists represents an error where the commit already exists.
type ErrCommitExists struct {
	Commit *pfs.Commit
}

// ErrCommitFinished represents an error where the commit has been finished
// (e.g from PutFile or DeleteFile)
type ErrCommitFinished struct {
	Commit *pfs.Commit
}

// ErrCommitDeleted represents an error where the commit has been deleted (e.g.
// from InspectCommit)
type ErrCommitDeleted struct {
	Commit *pfs.Commit
}

// ErrParentCommitNotFound represents a parent-commit-not-found error.
type ErrParentCommitNotFound struct {
	Commit *pfs.Commit
}

func (e ErrFileNotFound) Error() string {
	return fmt.Sprintf("file %v not found in repo %v at commit %v", e.File.Path, e.File.Commit.Repo.Name, e.File.Commit.ID)
}

func (e ErrRepoNotFound) Error() string {
	return fmt.Sprintf("repo %v not found", e.Repo.Name)
}

func (e ErrRepoExists) Error() string {
	return fmt.Sprintf("repo %v already exists", e.Repo.Name)
}

func (e ErrCommitNotFound) Error() string {
	return fmt.Sprintf("commit %v not found in repo %v", e.Commit.ID, e.Commit.Repo.Name)
}

func (e ErrNoHead) Error() string {
	return fmt.Sprintf("the branch \"%s\" has no head (create one with start-commit)", e.Branch.Name)
}

func (e ErrCommitExists) Error() string {
	return fmt.Sprintf("commit %v already exists in repo %v", e.Commit.ID, e.Commit.Repo.Name)
}

func (e ErrCommitFinished) Error() string {
	return fmt.Sprintf("commit %v in repo %v has already finished", e.Commit.ID, e.Commit.Repo.Name)
}

func (e ErrCommitDeleted) Error() string {
	return fmt.Sprintf("commit %v/%v was deleted", e.Commit.Repo.Name, e.Commit.ID)
}

func (e ErrParentCommitNotFound) Error() string {
	return fmt.Sprintf("parent commit %v not found in repo %v", e.Commit.ID, e.Commit.Repo.Name)
}

// ByteRangeSize returns byteRange.Upper - byteRange.Lower.
func ByteRangeSize(byteRange *pfs.ByteRange) uint64 {
	return byteRange.Upper - byteRange.Lower
}

var commitNotFoundRe = regexp.MustCompile("commit [^ ]+ not found in repo [^ ]+")

// IsCommitNotFoundErr returns true if 'err' has an error message that matches
// ErrCommitNotFound
func IsCommitNotFoundErr(err error) bool {
	if err == nil {
		return false
	}
	return commitNotFoundRe.MatchString(grpcutil.ScrubGRPC(err).Error())
}

var commitDeletedRe = regexp.MustCompile("commit [^ ]+/[^ ]+ was deleted")

// IsCommitDeletedErr returns true if 'err' has an error message that matches
// ErrCommitDeleted
func IsCommitDeletedErr(err error) bool {
	if err == nil {
		return false
	}
	return commitDeletedRe.MatchString(grpcutil.ScrubGRPC(err).Error())
}
<commit_msg>Add comment warning that the dash is matching an error message<commit_after>package pfs

import (
	"fmt"
	"regexp"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/pachyderm/pachyderm/src/client/pkg/grpcutil"
)

// ErrFileNotFound represents a file-not-found error.
type ErrFileNotFound struct {
	File *pfs.File
}

// ErrRepoNotFound represents a repo-not-found error.
type ErrRepoNotFound struct {
	Repo *pfs.Repo
}

// ErrRepoExists represents a repo-exists error.
type ErrRepoExists struct {
	Repo *pfs.Repo
}

// ErrCommitNotFound represents a commit-not-found error.
type ErrCommitNotFound struct {
	Commit *pfs.Commit
}

// ErrNoHead represents an error encountered because a branch has no head (e.g.
// inspectCommit(master) when 'master' has no commits)
type ErrNoHead struct {
	Branch *pfs.Branch
}

// ErrCommitExists represents an error where the commit already exists.
type ErrCommitExists struct {
	Commit *pfs.Commit
}

// ErrCommitFinished represents an error where the commit has been finished
// (e.g from PutFile or DeleteFile)
type ErrCommitFinished struct {
	Commit *pfs.Commit
}

// ErrCommitDeleted represents an error where the commit has been deleted (e.g.
// from InspectCommit)
type ErrCommitDeleted struct {
	Commit *pfs.Commit
}

// ErrParentCommitNotFound represents a parent-commit-not-found error.
type ErrParentCommitNotFound struct {
	Commit *pfs.Commit
}

func (e ErrFileNotFound) Error() string {
	return fmt.Sprintf("file %v not found in repo %v at commit %v", e.File.Path, e.File.Commit.Repo.Name, e.File.Commit.ID)
}

func (e ErrRepoNotFound) Error() string {
	return fmt.Sprintf("repo %v not found", e.Repo.Name)
}

func (e ErrRepoExists) Error() string {
	return fmt.Sprintf("repo %v already exists", e.Repo.Name)
}

func (e ErrCommitNotFound) Error() string {
	return fmt.Sprintf("commit %v not found in repo %v", e.Commit.ID, e.Commit.Repo.Name)
}

func (e ErrNoHead) Error() string {
	// the dashboard is matching on this message in stats. Please open an issue on the dash before changing this
	return fmt.Sprintf("the branch \"%s\" has no head (create one with start-commit)", e.Branch.Name)
}

func (e ErrCommitExists) Error() string {
	return fmt.Sprintf("commit %v already exists in repo %v", e.Commit.ID, e.Commit.Repo.Name)
}

func (e ErrCommitFinished) Error() string {
	return fmt.Sprintf("commit %v in repo %v has already finished", e.Commit.ID, e.Commit.Repo.Name)
}

func (e ErrCommitDeleted) Error() string {
	return fmt.Sprintf("commit %v/%v was deleted", e.Commit.Repo.Name, e.Commit.ID)
}

func (e ErrParentCommitNotFound) Error() string {
	return fmt.Sprintf("parent commit %v not found in repo %v", e.Commit.ID, e.Commit.Repo.Name)
}

// ByteRangeSize returns byteRange.Upper - byteRange.Lower.
func ByteRangeSize(byteRange *pfs.ByteRange) uint64 {
	return byteRange.Upper - byteRange.Lower
}

var commitNotFoundRe = regexp.MustCompile("commit [^ ]+ not found in repo [^ ]+")

// IsCommitNotFoundErr returns true if 'err' has an error message that matches
// ErrCommitNotFound
func IsCommitNotFoundErr(err error) bool {
	if err == nil {
		return false
	}
	return commitNotFoundRe.MatchString(grpcutil.ScrubGRPC(err).Error())
}

var commitDeletedRe = regexp.MustCompile("commit [^ ]+/[^ ]+ was deleted")

// IsCommitDeletedErr returns true if 'err' has an error message that matches
// ErrCommitDeleted
func IsCommitDeletedErr(err error) bool {
	if err == nil {
		return false
	}
	return commitDeletedRe.MatchString(grpcutil.ScrubGRPC(err).Error())
}
<|endoftext|>