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

package user

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

	"github.com/google/exposure-notifications-verification-server/pkg/api"
	"github.com/google/exposure-notifications-verification-server/pkg/controller"
	"github.com/google/exposure-notifications-verification-server/pkg/database"
	"github.com/hashicorp/go-multierror"
)

func (c *Controller) HandleImportBatch() http.Handler {
	logger := c.logger.Named("user.HandleImportBatch")
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()

		realm := controller.RealmFromContext(ctx)
		if realm == nil {
			controller.MissingRealm(w, r, c.h)
			return
		}

		currentUser := controller.UserFromContext(ctx)
		if currentUser == nil {
			controller.MissingUser(w, r, c.h)
			return
		}

		var request api.UserBatchRequest
		if err := controller.BindJSON(w, r, &request); err != nil {
			logger.Errorw("Error decoding request", "error", err)
			c.h.RenderJSON(w, http.StatusBadRequest, api.Error(err))
			return
		}

		newUsers := make([]*api.BatchUser, 0, len(request.Users))

		var batchErr *multierror.Error
		for _, batchUser := range request.Users {
			// See if the user already exists by email - they may be a member of another
			// realm.
			user, err := c.db.FindUserByEmail(batchUser.Email)
			if err != nil {
				if !database.IsNotFound(err) {
					logger.Errorw("Error finding user", "error", err)
					batchErr = multierror.Append(batchErr, err)
					continue
				}

				user = new(database.User)
				user.Email = batchUser.Email
				user.Name = batchUser.Name
			}
			user.Realms = append(user.Realms, realm)

			if created, err := user.CreateFirebaseUser(ctx, c.client); err != nil {
				logger.Errorw("Error creating firebase user", "error", err)
				batchErr = multierror.Append(batchErr, err)
				continue
			} else if created {
				newUsers = append(newUsers, &batchUser)

				if err := c.sendInvitation(ctx, user.Email); err != nil {
					batchErr = multierror.Append(batchErr, errors.New("send invitation failed"))
					continue
				}
			}

			if err := c.db.SaveUser(user, currentUser); err != nil {
				logger.Errorw("Error saving user", "error", err)
				batchErr = multierror.Append(batchErr, err)
				continue
			}
		}

		response := &api.UserBatchResponse{
			NewUsers: newUsers,
		}

		if err := batchErr.ErrorOrNil(); err != nil {
			response.Error = err.Error()
			response.ErrorCode = string(http.StatusInternalServerError)

			if len(newUsers) == 0 { // We return partial success if any succeeded.
				c.h.RenderJSON(w, http.StatusInternalServerError, response)
				return
			}
		}

		c.h.RenderJSON(w, http.StatusOK, response)
	})
}

func (c *Controller) sendInvitation(ctx context.Context, toEmail string) error {
	// Send email with emailer
	if c.emailer != nil {
		realmName := ""
		if realm := controller.RealmFromContext(ctx); realm != nil {
			realmName = realm.Name
		}

		from := c.emailer.From()
		message, err := controller.ComposeInviteEmail(ctx, c.h, c.client, toEmail, from, realmName)
		if err != nil {
			c.logger.Warnw("failed composing invitation", "error", err)
			return fmt.Errorf("failed composing invitation: %w", err)
		}
		if err := c.emailer.SendEmail(ctx, toEmail, message); err != nil {
			c.logger.Warnw("failed sending invitation", "error", err)
			return fmt.Errorf("failed sending invitation: %w", err)
		}

		return nil
	}

	// Fallback to Firebase

	if err := c.firebaseInternal.SendNewUserInvitation(ctx, toEmail); err != nil {
		c.logger.Warnw("failed sending invitation", "error", err)
		return fmt.Errorf("failed sending invitation: %w", err)
	}
	return nil
}
<commit_msg>Fix errorcode conversion to string (#856)<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package user

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

	"github.com/google/exposure-notifications-verification-server/pkg/api"
	"github.com/google/exposure-notifications-verification-server/pkg/controller"
	"github.com/google/exposure-notifications-verification-server/pkg/database"
	"github.com/hashicorp/go-multierror"
)

func (c *Controller) HandleImportBatch() http.Handler {
	logger := c.logger.Named("user.HandleImportBatch")
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()

		realm := controller.RealmFromContext(ctx)
		if realm == nil {
			controller.MissingRealm(w, r, c.h)
			return
		}

		currentUser := controller.UserFromContext(ctx)
		if currentUser == nil {
			controller.MissingUser(w, r, c.h)
			return
		}

		var request api.UserBatchRequest
		if err := controller.BindJSON(w, r, &request); err != nil {
			logger.Errorw("Error decoding request", "error", err)
			c.h.RenderJSON(w, http.StatusBadRequest, api.Error(err))
			return
		}

		newUsers := make([]*api.BatchUser, 0, len(request.Users))

		var batchErr *multierror.Error
		for _, batchUser := range request.Users {
			// See if the user already exists by email - they may be a member of another
			// realm.
			user, err := c.db.FindUserByEmail(batchUser.Email)
			if err != nil {
				if !database.IsNotFound(err) {
					logger.Errorw("Error finding user", "error", err)
					batchErr = multierror.Append(batchErr, err)
					continue
				}

				user = new(database.User)
				user.Email = batchUser.Email
				user.Name = batchUser.Name
			}
			user.Realms = append(user.Realms, realm)

			if created, err := user.CreateFirebaseUser(ctx, c.client); err != nil {
				logger.Errorw("Error creating firebase user", "error", err)
				batchErr = multierror.Append(batchErr, err)
				continue
			} else if created {
				newUsers = append(newUsers, &batchUser)

				if err := c.sendInvitation(ctx, user.Email); err != nil {
					batchErr = multierror.Append(batchErr, errors.New("send invitation failed"))
					continue
				}
			}

			if err := c.db.SaveUser(user, currentUser); err != nil {
				logger.Errorw("Error saving user", "error", err)
				batchErr = multierror.Append(batchErr, err)
				continue
			}
		}

		response := &api.UserBatchResponse{
			NewUsers: newUsers,
		}

		if err := batchErr.ErrorOrNil(); err != nil {
			response.Error = err.Error()
			response.ErrorCode = fmt.Sprintf("%d", http.StatusInternalServerError)

			if len(newUsers) == 0 { // We return partial success if any succeeded.
				c.h.RenderJSON(w, http.StatusInternalServerError, response)
				return
			}
		}

		c.h.RenderJSON(w, http.StatusOK, response)
	})
}

func (c *Controller) sendInvitation(ctx context.Context, toEmail string) error {
	// Send email with emailer
	if c.emailer != nil {
		realmName := ""
		if realm := controller.RealmFromContext(ctx); realm != nil {
			realmName = realm.Name
		}

		from := c.emailer.From()
		message, err := controller.ComposeInviteEmail(ctx, c.h, c.client, toEmail, from, realmName)
		if err != nil {
			c.logger.Warnw("failed composing invitation", "error", err)
			return fmt.Errorf("failed composing invitation: %w", err)
		}
		if err := c.emailer.SendEmail(ctx, toEmail, message); err != nil {
			c.logger.Warnw("failed sending invitation", "error", err)
			return fmt.Errorf("failed sending invitation: %w", err)
		}

		return nil
	}

	// Fallback to Firebase

	if err := c.firebaseInternal.SendNewUserInvitation(ctx, toEmail); err != nil {
		c.logger.Warnw("failed sending invitation", "error", err)
		return fmt.Errorf("failed sending invitation: %w", err)
	}
	return nil
}
<|endoftext|>


<commit_before>package postcommit

import (
	"github.com/libgit2/git2go"

	"github.com/rgeorgiev583/gonflator/translator"
)

func TranslateRepoHead(target Translator) (translatedRdiff <-chan Delta, err error) {
	gitRepo, err := git2go.OpenRepository(".")
	if err != nil {
		return
	}
	repo := GitRepository(gitRepo)

	head, err := repo.Head()
	if err != nil {
		return
	}

	commit, err := head.Peel(ObjectCommit)
	if err != nil {
		return
	}

	tree, err := commit.Tree()
	if err != nil {
		return
	}

	parentTree := commit.Parent(0).Tree()
	if err != nil {
		return
	}

	diff, err := repo.DiffTreeToTree(parentTree, tree, nil)
	if err != nil {
		return
	}

	diff := repo.GetRdiff(repo.GetDiffDeltas(diff))

	if target != nil {
		return target.TranslateRdiff(diff)
	} else {
		return diff
	}
}
<commit_msg>redesign: TranslateRepoHead now accepts a path as its second argument<commit_after>package postcommit

import (
	"github.com/libgit2/git2go"

	"github.com/rgeorgiev583/gonflator/translator"
)

func TranslateRepoHead(target Translator, path string) (translatedRdiff <-chan Delta, err error) {
	if path == "" {
		path = "."
	}
	gitRepo, err := git2go.OpenRepository(path)
	if err != nil {
		return
	}
	repo := GitRepository(gitRepo)

	head, err := repo.Head()
	if err != nil {
		return
	}

	commit, err := head.Peel(ObjectCommit)
	if err != nil {
		return
	}

	tree, err := commit.Tree()
	if err != nil {
		return
	}

	parentTree := commit.Parent(0).Tree()
	if err != nil {
		return
	}

	diff, err := repo.DiffTreeToTree(parentTree, tree, nil)
	if err != nil {
		return
	}

	diff := repo.GetRdiff(repo.GetDiffDeltas(diff))

	if target != nil {
		return target.TranslateRdiff(diff)
	} else {
		return diff
	}
}
<|endoftext|>


<commit_before>// Copyright The OpenTelemetry 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.

// Skip tests on Windows temporarily, see https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/11451
//go:build !windows
// +build !windows

// nolint:errcheck
package dbstorage

import (
	"context"
	"fmt"
	"sync"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/component/componenttest"
	"go.opentelemetry.io/collector/config"
	"go.opentelemetry.io/collector/extension/experimental/storage"
)

func TestExtensionIntegrity(t *testing.T) {
	ctx := context.Background()
	se := newTestExtension(t)
	err := se.Start(context.Background(), componenttest.NewNopHost())
	defer se.Shutdown(context.Background())
	assert.NoError(t, err)

	type mockComponent struct {
		kind component.Kind
		name config.ComponentID
	}

	components := []mockComponent{
		{kind: component.KindReceiver, name: newTestEntity("receiver_one")},
		{kind: component.KindReceiver, name: newTestEntity("receiver_two")},
		{kind: component.KindProcessor, name: newTestEntity("processor_one")},
		{kind: component.KindProcessor, name: newTestEntity("processor_two")},
		{kind: component.KindExporter, name: newTestEntity("exporter_one")},
		{kind: component.KindExporter, name: newTestEntity("exporter_two")},
		{kind: component.KindExtension, name: newTestEntity("extension_one")},
		{kind: component.KindExtension, name: newTestEntity("extension_two")},
	}

	// Make a client for each component
	clients := make(map[config.ComponentID]storage.Client)
	for _, c := range components {
		client, err := se.GetClient(ctx, c.kind, c.name, "")
		require.NoError(t, err)
		clients[c.name] = client
	}

	thrashClient := func(wg *sync.WaitGroup, n config.ComponentID, c storage.Client) {
		// keys and values
		keys := []string{"a", "b", "c", "d", "e"}
		myBytes := []byte(n.Name())

		// Set my values
		for i := 0; i < len(keys); i++ {
			err := c.Set(ctx, keys[i], myBytes)
			require.NoError(t, err)
		}

		// Repeatedly thrash client
		for j := 0; j < 100; j++ {

			// Make sure my values are still mine
			for i := 0; i < len(keys); i++ {
				v, err := c.Get(ctx, keys[i])
				require.NoError(t, err)
				require.Equal(t, myBytes, v)
			}

			// Delete my values
			for i := 0; i < len(keys); i++ {
				err := c.Delete(ctx, keys[i])
				require.NoError(t, err)
			}

			// Reset my values
			for i := 0; i < len(keys); i++ {
				err := c.Set(ctx, keys[i], myBytes)
				require.NoError(t, err)
			}
		}
		c.Close(ctx)
		wg.Done()
	}

	// Use clients concurrently
	var wg sync.WaitGroup
	for name, client := range clients {
		wg.Add(1)
		go thrashClient(&wg, name, client)
	}
	wg.Wait()
}

func newTestExtension(t *testing.T) storage.Extension {
	f := NewFactory()
	cfg := f.CreateDefaultConfig().(*Config)
	cfg.DriverName = "sqlite3"
	cfg.DataSource = fmt.Sprintf("file:%s/foo.db?_busy_timeout=10000&_journal=WAL&_sync=NORMAL", t.TempDir())

	extension, err := f.CreateExtension(context.Background(), componenttest.NewNopExtensionCreateSettings(), cfg)
	require.NoError(t, err)

	se, ok := extension.(storage.Extension)
	require.True(t, ok)

	return se
}

func newTestEntity(name string) config.ComponentID {
	return config.NewComponentIDWithName("nop", name)
}
<commit_msg>fix errcheck for extension dbstorage (#11538)<commit_after>// Copyright The OpenTelemetry 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.

// Skip tests on Windows temporarily, see https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/11451
//go:build !windows
// +build !windows

package dbstorage

import (
	"context"
	"fmt"
	"sync"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/component/componenttest"
	"go.opentelemetry.io/collector/config"
	"go.opentelemetry.io/collector/extension/experimental/storage"
)

func TestExtensionIntegrity(t *testing.T) {
	ctx := context.Background()
	se := newTestExtension(t)
	err := se.Start(context.Background(), componenttest.NewNopHost())
	assert.NoError(t, err)
	defer func() {
		err = se.Shutdown(context.Background())
		assert.NoError(t, err)
	}()

	type mockComponent struct {
		kind component.Kind
		name config.ComponentID
	}

	components := []mockComponent{
		{kind: component.KindReceiver, name: newTestEntity("receiver_one")},
		{kind: component.KindReceiver, name: newTestEntity("receiver_two")},
		{kind: component.KindProcessor, name: newTestEntity("processor_one")},
		{kind: component.KindProcessor, name: newTestEntity("processor_two")},
		{kind: component.KindExporter, name: newTestEntity("exporter_one")},
		{kind: component.KindExporter, name: newTestEntity("exporter_two")},
		{kind: component.KindExtension, name: newTestEntity("extension_one")},
		{kind: component.KindExtension, name: newTestEntity("extension_two")},
	}

	// Make a client for each component
	clients := make(map[config.ComponentID]storage.Client)
	for _, c := range components {
		client, err := se.GetClient(ctx, c.kind, c.name, "")
		require.NoError(t, err)
		clients[c.name] = client
	}

	thrashClient := func(wg *sync.WaitGroup, n config.ComponentID, c storage.Client) {
		// keys and values
		keys := []string{"a", "b", "c", "d", "e"}
		myBytes := []byte(n.Name())

		// Set my values
		for i := 0; i < len(keys); i++ {
			err := c.Set(ctx, keys[i], myBytes)
			require.NoError(t, err)
		}

		// Repeatedly thrash client
		for j := 0; j < 100; j++ {

			// Make sure my values are still mine
			for i := 0; i < len(keys); i++ {
				v, err := c.Get(ctx, keys[i])
				require.NoError(t, err)
				require.Equal(t, myBytes, v)
			}

			// Delete my values
			for i := 0; i < len(keys); i++ {
				err := c.Delete(ctx, keys[i])
				require.NoError(t, err)
			}

			// Reset my values
			for i := 0; i < len(keys); i++ {
				err := c.Set(ctx, keys[i], myBytes)
				require.NoError(t, err)
			}
		}
		c.Close(ctx)
		wg.Done()
	}

	// Use clients concurrently
	var wg sync.WaitGroup
	for name, client := range clients {
		wg.Add(1)
		go thrashClient(&wg, name, client)
	}
	wg.Wait()
}

func newTestExtension(t *testing.T) storage.Extension {
	f := NewFactory()
	cfg := f.CreateDefaultConfig().(*Config)
	cfg.DriverName = "sqlite3"
	cfg.DataSource = fmt.Sprintf("file:%s/foo.db?_busy_timeout=10000&_journal=WAL&_sync=NORMAL", t.TempDir())

	extension, err := f.CreateExtension(context.Background(), componenttest.NewNopExtensionCreateSettings(), cfg)
	require.NoError(t, err)

	se, ok := extension.(storage.Extension)
	require.True(t, ok)

	return se
}

func newTestEntity(name string) config.ComponentID {
	return config.NewComponentIDWithName("nop", name)
}
<|endoftext|>


<commit_before>package spn

import (
	"github.com/RenatoGeh/gospn/utils"
)

// Indicator is an indicator node of a variable value X=x. Its value is 1 if X=x or is not set, and
// 0 otherwise.
type Indicator struct {
	Node
	// Variable ID
	varid int
	// Value of variable
	v int
}

// NewIndicator constructs a new indicator node.
func NewIndicator(varid int, v int) *Indicator {
	return &Indicator{Node{nil, []int{varid}}, varid, v}
}

// Type returns the type of this node.
func (i *Indicator) Type() string { return "leaf" }

// Value returns the probability of a certain valuation. In the case of an indicator node, 1 if X=x
// or is not set and 0 otherwise.
func (i *Indicator) Value(val VarSet) float64 {
	u, e := val[i.varid]
	if !e || u == i.v {
		return 0
	}
	return utils.LogZero
}

// Max returns the MAP.
func (i *Indicator) Max(val VarSet) float64 {
	u, e := val[i.varid]
	if !e || u == i.v {
		return 0
	}
	return utils.LogZero
}

// ArgMax returns the MAP and the MAP state.
func (i *Indicator) ArgMax(val VarSet) (VarSet, float64) {
	retval := make(VarSet)
	u, e := val[i.varid]
	if !e || u == i.v {
		retval[i.varid] = u
		return retval, 0
	}
	return retval, utils.LogZero
}

// Sc returns the scope of this node.
func (i *Indicator) Sc() []int {
	if len(i.sc) == 0 {
		i.sc = []int{i.varid}
	}
	return i.sc
}
<commit_msg>spn: added indicator serialization<commit_after>package spn

import (
	"bytes"
	"fmt"
	"github.com/RenatoGeh/gospn/utils"
)

// Indicator is an indicator node of a variable value X=x. Its value is 1 if X=x or is not set, and
// 0 otherwise.
type Indicator struct {
	Node
	// Variable ID
	varid int
	// Value of variable
	v int
}

// NewIndicator constructs a new indicator node.
func NewIndicator(varid int, v int) *Indicator {
	return &Indicator{Node{nil, []int{varid}}, varid, v}
}

// Type returns the type of this node.
func (i *Indicator) Type() string { return "leaf" }

// Value returns the probability of a certain valuation. In the case of an indicator node, 1 if X=x
// or is not set and 0 otherwise.
func (i *Indicator) Value(val VarSet) float64 {
	u, e := val[i.varid]
	if !e || u == i.v {
		return 0
	}
	return utils.LogZero
}

// Max returns the MAP.
func (i *Indicator) Max(val VarSet) float64 {
	u, e := val[i.varid]
	if !e || u == i.v {
		return 0
	}
	return utils.LogZero
}

// ArgMax returns the MAP and the MAP state.
func (i *Indicator) ArgMax(val VarSet) (VarSet, float64) {
	retval := make(VarSet)
	u, e := val[i.varid]
	if !e || u == i.v {
		retval[i.varid] = u
		return retval, 0
	}
	return retval, utils.LogZero
}

// Sc returns the scope of this node.
func (i *Indicator) Sc() []int {
	if len(i.sc) == 0 {
		i.sc = []int{i.varid}
	}
	return i.sc
}

func (i *Indicator) GobEncode() ([]byte, error) {
	var b bytes.Buffer
	fmt.Fprintln(&b, i.varid, i.v)
	return b.Bytes(), nil
}

func (i *Indicator) GobDecode(data []byte) error {
	b := bytes.NewBuffer(data)
	_, err := fmt.Fscanf(b, "%d %d", &i.varid, &i.v)
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"math"
	"strings"
)

const (
	// characters used for short-urls
	SYMBOLS = "0123456789abcdefghijklmnopqrsuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ"

	// someone set us up the bomb !!
	BASE = int64(len(SYMBOLS))
)

// encodes a number into our *base* representation
// TODO can this be made better with some bitshifting?
func Encode(number int64) string {
	rest := number % BASE
	// strings are a bit weird in go...
	result := string(SYMBOLS[rest])
	if number-rest != 0 {
		newnumber := (number - rest) / BASE
		result = Encode(newnumber) + result
	}
	return result
}

// Decodes a string given in our encoding and returns the decimal
// integer.
func Decode(input string) int64 {
	const floatbase = float64(BASE)
	l := len(input)
	var sum int = 0
	for index := l - 1; index > -1; index -= 1 {
		current := string(input[index])
		pos := strings.Index(SYMBOLS, current)
		sum = sum + (pos * int(math.Pow(floatbase, float64((l-index-1)))))
	}
	return int64(sum)
}
<commit_msg>added license<commit_after>/*
https://github.com/fs111/kurz.go/blob/master/src/codec.go

Copyright (c) 2011 André Kelpe

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package main

import (
	"math"
	"strings"
)

const (
	// characters used for short-urls
	SYMBOLS = "0123456789abcdefghijklmnopqrsuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ"

	// someone set us up the bomb !!
	BASE = int64(len(SYMBOLS))
)

// encodes a number into our *base* representation
// TODO can this be made better with some bitshifting?
func Encode(number int64) string {
	rest := number % BASE
	// strings are a bit weird in go...
	result := string(SYMBOLS[rest])
	if number-rest != 0 {
		newnumber := (number - rest) / BASE
		result = Encode(newnumber) + result
	}
	return result
}

// Decodes a string given in our encoding and returns the decimal
// integer.
func Decode(input string) int64 {
	const floatbase = float64(BASE)
	l := len(input)
	var sum int = 0
	for index := l - 1; index > -1; index -= 1 {
		current := string(input[index])
		pos := strings.Index(SYMBOLS, current)
		sum = sum + (pos * int(math.Pow(floatbase, float64((l-index-1)))))
	}
	return int64(sum)
}
<|endoftext|>


<commit_before>// Package translation provides a simple in-memory translation service - it may soon be renamed translate
package translation

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"
)

// DefaultLanguage defines a default language to fall back to
var DefaultLanguage = "en"

// data holds the translated data in memory (at present not split by language)
var data map[string]string

// mu guards the translations during load and access
var mu sync.RWMutex

// Load scans the path for translation lang.json files
func Load(root string) error {
	// Lock data for load operation
	mu.Lock()
	defer mu.Unlock()
	data = make(map[string]string)

	// Scan the files in the given dir, looking for our suffix
	err := filepath.Walk(root, func(p string, info os.FileInfo, err error) error {

		if err != nil {
			return err
		}

		// Deal with files, directories we return nil error to recurse on them
		if canParseFile(p) {
			err = parseFile(p)
			if err != nil {
				return err
			}
		}

		return nil
	})

	return err
}

// Get returns the translation for a given language and key
// if no result, it falls back to DefaultLanguage + key
func Get(lang, key string) string {
	mu.RLock()
	defer mu.RUnlock()

	// First try the language specified
	t := data[lang+key]
	if t != "" {
		return t
	}

	// Fall back to default language if no result (in our case english)
	t = data[DefaultLanguage+key]
	if t != "" {
		return t
	}

	// If still no result, return key
	return key
}

// canParseFile returns true if we can parse this file
func canParseFile(p string) bool {
	return !strings.HasPrefix(p, ".") && strings.HasSuffix(p, ".lang.json")
}

// parseFile opens the file and fills in our translations,
// returning error if a problem is encountered.
func parseFile(p string) error {

	// For each file, load all strings in the json file,
	//  and add them to our list of translations
	file, err := ioutil.ReadFile(p)
	if err != nil {
		return fmt.Errorf("Error opening file %s %v", p, err)
	}

	var langData map[string]string
	err = json.Unmarshal(file, &langData)
	if err != nil {
		return fmt.Errorf("Error reading language file %s %v", p, err)
	}

	lang := path.Base(p)
	lang = strings.Replace(lang, ".lang.json", "", -1)

	for k, v := range langData {
		data[lang+k] = v
	}

	return nil
}
<commit_msg>Ensure translations.Load calls setup only once<commit_after>// Package translation provides a simple in-memory translation service - it may soon be renamed translate
package translation

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"
)

// DefaultLanguage defines a default language to fall back to
var DefaultLanguage = "en"

// data holds the translated data in memory (at present not split by language)
var data map[string]string

// mu guards the translations during load and access
var mu sync.RWMutex

var setupComplete bool

// Setup sets up the initial map
func Setup() error {
	mu.Lock()
	defer mu.Unlock()
	data = make(map[string]string)
	setupComplete = true
	return nil
}

// Load scans the path for translation lang.json files
// if called twice the second translations will overwrite any common keys
func Load(root string) error {
	// Ensure setup was called
	if !setupComplete {
		err := Setup()
		if err != nil {
			return err
		}
	}

	// Lock data for load operation
	mu.Lock()
	defer mu.Unlock()

	// Scan the files in the given dir, looking for our suffix
	err := filepath.Walk(root, func(p string, info os.FileInfo, err error) error {

		if err != nil {
			return err
		}

		// Deal with files, directories we return nil error to recurse on them
		if canParseFile(p) {
			err = parseFile(p)
			if err != nil {
				return err
			}
		}

		return nil
	})

	return err
}

// Get returns the translation for a given language and key
// if no result, it falls back to DefaultLanguage + key
func Get(lang, key string) string {
	mu.RLock()
	defer mu.RUnlock()

	// First try the language specified
	t := data[lang+key]
	if t != "" {
		return t
	}

	// Fall back to default language if no result (in our case english)
	t = data[DefaultLanguage+key]
	if t != "" {
		return t
	}

	// If still no result, return key
	return key
}

// canParseFile returns true if we can parse this file
func canParseFile(p string) bool {
	return !strings.HasPrefix(p, ".") && strings.HasSuffix(p, ".lang.json")
}

// parseFile opens the file and fills in our translations,
// returning error if a problem is encountered.
func parseFile(p string) error {

	// For each file, load all strings in the json file,
	//  and add them to our list of translations
	file, err := ioutil.ReadFile(p)
	if err != nil {
		return fmt.Errorf("Error opening file %s %v", p, err)
	}

	var langData map[string]string
	err = json.Unmarshal(file, &langData)
	if err != nil {
		return fmt.Errorf("Error reading language file %s %v", p, err)
	}

	lang := path.Base(p)
	lang = strings.Replace(lang, ".lang.json", "", -1)

	for k, v := range langData {
		data[lang+k] = v
	}

	return nil
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"sync"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/depgraph"
)

// Terraform is the primary structure that is used to interact with
// Terraform from code, and can perform operations such as returning
// all resources, a resource tree, a specific resource, etc.
type Terraform struct {
	config    *config.Config
	graph     *depgraph.Graph
	mapping   map[*config.Resource]ResourceProvider
	variables map[string]string
}

// Config is the configuration that must be given to instantiate
// a Terraform structure.
type Config struct {
	Config    *config.Config
	Providers map[string]ResourceProviderFactory
	Variables map[string]string

	computedPlaceholder string
}

// New creates a new Terraform structure, initializes resource providers
// for the given configuration, etc.
//
// Semantic checks of the entire configuration structure are done at this
// time, as well as richer checks such as verifying that the resource providers
// can be properly initialized, can be configured, etc.
func New(c *Config) (*Terraform, error) {
	var errs []error

	// Calculate the computed key placeholder
	c.computedPlaceholder = "tf_computed_placeholder"

	// Validate that all required variables have values
	if err := smcVariables(c); err != nil {
		errs = append(errs, err...)
	}

	// Match all the resources with a provider and initialize the providers
	mapping, err := smcProviders(c)
	if err != nil {
		errs = append(errs, err...)
	}

	// Build the resource graph
	graph := c.Config.Graph()
	if err := graph.Validate(); err != nil {
		errs = append(errs, fmt.Errorf(
			"Resource graph has an error: %s", err))
	}

	// If we accumulated any errors, then return them all
	if len(errs) > 0 {
		return nil, &MultiError{Errors: errs}
	}

	return &Terraform{
		config:    c.Config,
		graph:     graph,
		mapping:   mapping,
		variables: c.Variables,
	}, nil
}

func (t *Terraform) Apply(*State, *Diff) (*State, error) {
	return nil, nil
}

func (t *Terraform) Diff(s *State) (*Diff, error) {
	result := new(Diff)
	err := t.graph.Walk(t.diffWalkFn(s, result))
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (t *Terraform) Refresh(*State) (*State, error) {
	return nil, nil
}

func (t *Terraform) diffWalkFn(
	state *State, result *Diff) depgraph.WalkFunc {
	var l sync.RWMutex

	// Initialize the result diff so we can write to it
	result.init()

	// This is the value that will be used for computed properties
	computedId := "computed"

	// Initialize the variables for application
	vars := make(map[string]string)
	for k, v := range t.variables {
		vars[k] = v
	}

	return func(n *depgraph.Noun) error {
		// If it is the root node, ignore
		if n.Meta == nil {
			return nil
		}

		r := n.Meta.(*config.Resource)
		p := t.mapping[r]
		if p == nil {
			panic(fmt.Sprintf("No provider for resource: %s", r.Id()))
		}

		l.RLock()
		var rs *ResourceState
		if state != nil {
			rs = state.resources[r.Id()]
		}
		if len(vars) > 0 {
			r = r.ReplaceVariables(vars)
		}
		l.RUnlock()

		diff, err := p.Diff(rs, r.Config)
		if err != nil {
			return err
		}

		// If there were no diff items, return right away
		if len(diff.Attributes) == 0 {
			return nil
		}

		// Acquire a lock since this function is called in parallel
		l.Lock()
		defer l.Unlock()

		// Update the resulting diff
		result.Resources[r.Id()] = diff.Attributes

		// Determine the new state and update variables
		rs = rs.MergeDiff(diff.Attributes, computedId)
		for ak, av := range rs.Attributes {
			vars[fmt.Sprintf("%s.%s", r.Id(), ak)] = av
		}

		return nil
	}
}
<commit_msg>terraform: ignore ProviderConfig during walks<commit_after>package terraform

import (
	"fmt"
	"sync"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/depgraph"
)

// Terraform is the primary structure that is used to interact with
// Terraform from code, and can perform operations such as returning
// all resources, a resource tree, a specific resource, etc.
type Terraform struct {
	config    *config.Config
	graph     *depgraph.Graph
	mapping   map[*config.Resource]ResourceProvider
	variables map[string]string
}

// Config is the configuration that must be given to instantiate
// a Terraform structure.
type Config struct {
	Config    *config.Config
	Providers map[string]ResourceProviderFactory
	Variables map[string]string

	computedPlaceholder string
}

// New creates a new Terraform structure, initializes resource providers
// for the given configuration, etc.
//
// Semantic checks of the entire configuration structure are done at this
// time, as well as richer checks such as verifying that the resource providers
// can be properly initialized, can be configured, etc.
func New(c *Config) (*Terraform, error) {
	var errs []error

	// Calculate the computed key placeholder
	c.computedPlaceholder = "tf_computed_placeholder"

	// Validate that all required variables have values
	if err := smcVariables(c); err != nil {
		errs = append(errs, err...)
	}

	// Match all the resources with a provider and initialize the providers
	mapping, err := smcProviders(c)
	if err != nil {
		errs = append(errs, err...)
	}

	// Build the resource graph
	graph := c.Config.Graph()
	if err := graph.Validate(); err != nil {
		errs = append(errs, fmt.Errorf(
			"Resource graph has an error: %s", err))
	}

	// If we accumulated any errors, then return them all
	if len(errs) > 0 {
		return nil, &MultiError{Errors: errs}
	}

	return &Terraform{
		config:    c.Config,
		graph:     graph,
		mapping:   mapping,
		variables: c.Variables,
	}, nil
}

func (t *Terraform) Apply(*State, *Diff) (*State, error) {
	return nil, nil
}

func (t *Terraform) Diff(s *State) (*Diff, error) {
	result := new(Diff)
	err := t.graph.Walk(t.diffWalkFn(s, result))
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (t *Terraform) Refresh(*State) (*State, error) {
	return nil, nil
}

func (t *Terraform) diffWalkFn(
	state *State, result *Diff) depgraph.WalkFunc {
	var l sync.RWMutex

	// Initialize the result diff so we can write to it
	result.init()

	// This is the value that will be used for computed properties
	computedId := "computed"

	// Initialize the variables for application
	vars := make(map[string]string)
	for k, v := range t.variables {
		vars[k] = v
	}

	return func(n *depgraph.Noun) error {
		// If it is the root node, ignore
		if n.Meta == nil {
			return nil
		}

		switch n.Meta.(type) {
		case *config.ProviderConfig:
			// Ignore, we don't treat this any differently.
			return nil
		case *config.Resource:
			// Continue
		}

		r := n.Meta.(*config.Resource)
		p := t.mapping[r]
		if p == nil {
			panic(fmt.Sprintf("No provider for resource: %s", r.Id()))
		}

		l.RLock()
		var rs *ResourceState
		if state != nil {
			rs = state.resources[r.Id()]
		}
		if len(vars) > 0 {
			r = r.ReplaceVariables(vars)
		}
		l.RUnlock()

		diff, err := p.Diff(rs, r.Config)
		if err != nil {
			return err
		}

		// If there were no diff items, return right away
		if len(diff.Attributes) == 0 {
			return nil
		}

		// Acquire a lock since this function is called in parallel
		l.Lock()
		defer l.Unlock()

		// Update the resulting diff
		result.Resources[r.Id()] = diff.Attributes

		// Determine the new state and update variables
		rs = rs.MergeDiff(diff.Attributes, computedId)
		for ak, av := range rs.Attributes {
			vars[fmt.Sprintf("%s.%s", r.Id(), ak)] = av
		}

		return nil
	}
}
<|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 upgrade

import (
	"fmt"
	"io"
	"os"
	"sort"
	"strings"
	"text/tabwriter"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"k8s.io/apimachinery/pkg/util/version"
	"k8s.io/klog"
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
	"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
	"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
	configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
	etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd"
)

type planFlags struct {
	*applyPlanFlags
}

// NewCmdPlan returns the cobra command for `kubeadm upgrade plan`
func NewCmdPlan(apf *applyPlanFlags) *cobra.Command {
	flags := &planFlags{
		applyPlanFlags: apf,
	}

	cmd := &cobra.Command{
		Use:   "plan [version] [flags]",
		Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter.",
		Run: func(_ *cobra.Command, args []string) {
			var userVersion string
			var err error
			flags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors)
			kubeadmutil.CheckErr(err)
			// Ensure the user is root
			err = runPreflightChecks(flags.ignorePreflightErrorsSet)
			kubeadmutil.CheckErr(err)

			// If the version is specified in config file, pick up that value.
			if flags.cfgPath != "" {
				cfg, err := configutil.LoadInitConfigurationFromFile(flags.cfgPath)
				kubeadmutil.CheckErr(err)

				if cfg.KubernetesVersion != "" {
					userVersion = cfg.KubernetesVersion
				}
			}
			// If option was specified in both args and config file, args will overwrite the config file.
			if len(args) == 1 {
				userVersion = args[0]
			}

			err = runPlan(flags, userVersion)
			kubeadmutil.CheckErr(err)
		},
	}

	// Register the common flags for apply and plan
	addApplyPlanFlags(cmd.Flags(), flags.applyPlanFlags)
	return cmd
}

// runPlan takes care of outputting available versions to upgrade to for the user
func runPlan(flags *planFlags, userVersion string) error {
	// Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never dry-run when planning.
	klog.V(1).Infof("[upgrade/plan] verifying health of cluster")
	klog.V(1).Infof("[upgrade/plan] retrieving configuration from cluster")
	client, versionGetter, cfg, err := enforceRequirements(flags.applyPlanFlags, false, userVersion)
	if err != nil {
		return err
	}

	var etcdClient etcdutil.ClusterInterrogator

	// Currently this is the only method we have for distinguishing
	// external etcd vs static pod etcd
	isExternalEtcd := cfg.Etcd.External != nil
	if isExternalEtcd {
		client, err := etcdutil.New(
			cfg.Etcd.External.Endpoints,
			cfg.Etcd.External.CAFile,
			cfg.Etcd.External.CertFile,
			cfg.Etcd.External.KeyFile)
		if err != nil {
			return err
		}
		etcdClient = client
	} else {
		// Connects to local/stacked etcd existing in the cluster
		client, err := etcdutil.NewFromCluster(client, cfg.CertificatesDir)
		if err != nil {
			return err
		}
		etcdClient = client
	}

	// Compute which upgrade possibilities there are
	klog.V(1).Infof("[upgrade/plan] computing upgrade possibilities")
	availUpgrades, err := upgrade.GetAvailableUpgrades(versionGetter, flags.allowExperimentalUpgrades, flags.allowRCUpgrades, etcdClient, cfg.DNS.Type, client)
	if err != nil {
		return errors.Wrap(err, "[upgrade/versions] FATAL")
	}

	// Tell the user which upgrades are available
	printAvailableUpgrades(availUpgrades, os.Stdout, isExternalEtcd)
	return nil
}

// printAvailableUpgrades prints a UX-friendly overview of what versions are available to upgrade to
// TODO look into columnize or some other formatter when time permits instead of using the tabwriter
func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, isExternalEtcd bool) {

	// Return quickly if no upgrades can be made
	if len(upgrades) == 0 {
		fmt.Fprintln(w, "Awesome, you're up-to-date! Enjoy!")
		return
	}
	// The tab writer writes to the "real" writer w
	tabw := tabwriter.NewWriter(w, 10, 4, 3, ' ', 0)

	// Loop through the upgrade possibilities and output text to the command line
	for _, upgrade := range upgrades {

		newK8sVersion, err := version.ParseSemantic(upgrade.After.KubeVersion)
		if err != nil {
			fmt.Fprintf(w, "Unable to parse normalized version %q as a semantic version\n", upgrade.After.KubeVersion)
			continue
		}

		UnstableVersionFlag := ""
		if len(newK8sVersion.PreRelease()) != 0 {
			if strings.HasPrefix(newK8sVersion.PreRelease(), "rc") {
				UnstableVersionFlag = " --allow-release-candidate-upgrades"
			} else {
				UnstableVersionFlag = " --allow-experimental-upgrades"
			}
		}

		if isExternalEtcd && upgrade.CanUpgradeEtcd() {
			fmt.Fprintln(w, "External components that should be upgraded manually before you upgrade the control plane with 'kubeadm upgrade apply':")
			fmt.Fprintln(tabw, "COMPONENT\tCURRENT\tAVAILABLE")
			fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion)

			// We should flush the writer here at this stage; as the columns will now be of the right size, adjusted to the above content
			tabw.Flush()
			fmt.Fprintln(w, "")
		}

		if upgrade.CanUpgradeKubelets() {
			fmt.Fprintln(w, "Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':")
			fmt.Fprintln(tabw, "COMPONENT\tCURRENT\tAVAILABLE")
			firstPrinted := false

			// The map is of the form <old-version>:<node-count>. Here all the keys are put into a slice and sorted
			// in order to always get the right order. Then the map value is extracted separately
			for _, oldVersion := range sortedSliceFromStringIntMap(upgrade.Before.KubeletVersions) {
				nodeCount := upgrade.Before.KubeletVersions[oldVersion]
				if !firstPrinted {
					// Output the Kubelet header only on the first version pair
					fmt.Fprintf(tabw, "Kubelet\t%d x %s\t%s\n", nodeCount, oldVersion, upgrade.After.KubeVersion)
					firstPrinted = true
					continue
				}
				fmt.Fprintf(tabw, "\t%d x %s\t%s\n", nodeCount, oldVersion, upgrade.After.KubeVersion)
			}
			// We should flush the writer here at this stage; as the columns will now be of the right size, adjusted to the above content
			tabw.Flush()
			fmt.Fprintln(w, "")
		}

		fmt.Fprintf(w, "Upgrade to the latest %s:\n", upgrade.Description)
		fmt.Fprintln(w, "")
		fmt.Fprintln(tabw, "COMPONENT\tCURRENT\tAVAILABLE")
		fmt.Fprintf(tabw, "API Server\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
		fmt.Fprintf(tabw, "Controller Manager\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
		fmt.Fprintf(tabw, "Scheduler\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
		fmt.Fprintf(tabw, "Kube Proxy\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)

		// TODO There is currently no way to cleanly output upgrades that involve adding, removing, or changing components
		// https://github.com/kubernetes/kubeadm/issues/810 was created to track addressing this.
		printCoreDNS, printKubeDNS := false, false
		coreDNSBeforeVersion, coreDNSAfterVersion, kubeDNSBeforeVersion, kubeDNSAfterVersion := "", "", "", ""

		switch upgrade.Before.DNSType {
		case kubeadmapi.CoreDNS:
			printCoreDNS = true
			coreDNSBeforeVersion = upgrade.Before.DNSVersion
		case kubeadmapi.KubeDNS:
			printKubeDNS = true
			kubeDNSBeforeVersion = upgrade.Before.DNSVersion
		}

		switch upgrade.After.DNSType {
		case kubeadmapi.CoreDNS:
			printCoreDNS = true
			coreDNSAfterVersion = upgrade.After.DNSVersion
		case kubeadmapi.KubeDNS:
			printKubeDNS = true
			kubeDNSAfterVersion = upgrade.After.DNSVersion
		}

		if printCoreDNS {
			fmt.Fprintf(tabw, "CoreDNS\t%s\t%s\n", coreDNSBeforeVersion, coreDNSAfterVersion)
		}
		if printKubeDNS {
			fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", kubeDNSBeforeVersion, kubeDNSAfterVersion)
		}

		if !isExternalEtcd {
			fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion)
		}

		// The tabwriter should be flushed at this stage as we have now put in all the required content for this time. This is required for the tabs' size to be correct.
		tabw.Flush()
		fmt.Fprintln(w, "")
		fmt.Fprintln(w, "You can now apply the upgrade by executing the following command:")
		fmt.Fprintln(w, "")
		fmt.Fprintf(w, "\tkubeadm upgrade apply %s%s\n", upgrade.After.KubeVersion, UnstableVersionFlag)
		fmt.Fprintln(w, "")

		if upgrade.Before.KubeadmVersion != upgrade.After.KubeadmVersion {
			fmt.Fprintf(w, "Note: Before you can perform this upgrade, you have to update kubeadm to %s.\n", upgrade.After.KubeadmVersion)
			fmt.Fprintln(w, "")
		}

		fmt.Fprintln(w, "_____________________________________________________________________")
		fmt.Fprintln(w, "")
	}
}

// sortedSliceFromStringIntMap returns a slice of the keys in the map sorted alphabetically
func sortedSliceFromStringIntMap(strMap map[string]uint16) []string {
	strSlice := []string{}
	for k := range strMap {
		strSlice = append(strSlice, k)
	}
	sort.Strings(strSlice)
	return strSlice
}
<commit_msg>kubeadm: simplify creating etcdClient<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 upgrade

import (
	"fmt"
	"io"
	"os"
	"sort"
	"strings"
	"text/tabwriter"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"k8s.io/apimachinery/pkg/util/version"
	"k8s.io/klog"
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
	"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
	"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
	configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
	etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd"
)

type planFlags struct {
	*applyPlanFlags
}

// NewCmdPlan returns the cobra command for `kubeadm upgrade plan`
func NewCmdPlan(apf *applyPlanFlags) *cobra.Command {
	flags := &planFlags{
		applyPlanFlags: apf,
	}

	cmd := &cobra.Command{
		Use:   "plan [version] [flags]",
		Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter.",
		Run: func(_ *cobra.Command, args []string) {
			var userVersion string
			var err error
			flags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors)
			kubeadmutil.CheckErr(err)
			// Ensure the user is root
			err = runPreflightChecks(flags.ignorePreflightErrorsSet)
			kubeadmutil.CheckErr(err)

			// If the version is specified in config file, pick up that value.
			if flags.cfgPath != "" {
				cfg, err := configutil.LoadInitConfigurationFromFile(flags.cfgPath)
				kubeadmutil.CheckErr(err)

				if cfg.KubernetesVersion != "" {
					userVersion = cfg.KubernetesVersion
				}
			}
			// If option was specified in both args and config file, args will overwrite the config file.
			if len(args) == 1 {
				userVersion = args[0]
			}

			err = runPlan(flags, userVersion)
			kubeadmutil.CheckErr(err)
		},
	}

	// Register the common flags for apply and plan
	addApplyPlanFlags(cmd.Flags(), flags.applyPlanFlags)
	return cmd
}

// runPlan takes care of outputting available versions to upgrade to for the user
func runPlan(flags *planFlags, userVersion string) error {
	// Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never dry-run when planning.
	klog.V(1).Infof("[upgrade/plan] verifying health of cluster")
	klog.V(1).Infof("[upgrade/plan] retrieving configuration from cluster")
	client, versionGetter, cfg, err := enforceRequirements(flags.applyPlanFlags, false, userVersion)
	if err != nil {
		return err
	}

	var etcdClient etcdutil.ClusterInterrogator

	// Currently this is the only method we have for distinguishing
	// external etcd vs static pod etcd
	isExternalEtcd := cfg.Etcd.External != nil
	if isExternalEtcd {
		etcdClient, err = etcdutil.New(
			cfg.Etcd.External.Endpoints,
			cfg.Etcd.External.CAFile,
			cfg.Etcd.External.CertFile,
			cfg.Etcd.External.KeyFile)
	} else {
		// Connects to local/stacked etcd existing in the cluster
		etcdClient, err = etcdutil.NewFromCluster(client, cfg.CertificatesDir)
	}
	if err != nil {
		return err
	}

	// Compute which upgrade possibilities there are
	klog.V(1).Infof("[upgrade/plan] computing upgrade possibilities")
	availUpgrades, err := upgrade.GetAvailableUpgrades(versionGetter, flags.allowExperimentalUpgrades, flags.allowRCUpgrades, etcdClient, cfg.DNS.Type, client)
	if err != nil {
		return errors.Wrap(err, "[upgrade/versions] FATAL")
	}

	// Tell the user which upgrades are available
	printAvailableUpgrades(availUpgrades, os.Stdout, isExternalEtcd)
	return nil
}

// printAvailableUpgrades prints a UX-friendly overview of what versions are available to upgrade to
// TODO look into columnize or some other formatter when time permits instead of using the tabwriter
func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, isExternalEtcd bool) {

	// Return quickly if no upgrades can be made
	if len(upgrades) == 0 {
		fmt.Fprintln(w, "Awesome, you're up-to-date! Enjoy!")
		return
	}
	// The tab writer writes to the "real" writer w
	tabw := tabwriter.NewWriter(w, 10, 4, 3, ' ', 0)

	// Loop through the upgrade possibilities and output text to the command line
	for _, upgrade := range upgrades {

		newK8sVersion, err := version.ParseSemantic(upgrade.After.KubeVersion)
		if err != nil {
			fmt.Fprintf(w, "Unable to parse normalized version %q as a semantic version\n", upgrade.After.KubeVersion)
			continue
		}

		UnstableVersionFlag := ""
		if len(newK8sVersion.PreRelease()) != 0 {
			if strings.HasPrefix(newK8sVersion.PreRelease(), "rc") {
				UnstableVersionFlag = " --allow-release-candidate-upgrades"
			} else {
				UnstableVersionFlag = " --allow-experimental-upgrades"
			}
		}

		if isExternalEtcd && upgrade.CanUpgradeEtcd() {
			fmt.Fprintln(w, "External components that should be upgraded manually before you upgrade the control plane with 'kubeadm upgrade apply':")
			fmt.Fprintln(tabw, "COMPONENT\tCURRENT\tAVAILABLE")
			fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion)

			// We should flush the writer here at this stage; as the columns will now be of the right size, adjusted to the above content
			tabw.Flush()
			fmt.Fprintln(w, "")
		}

		if upgrade.CanUpgradeKubelets() {
			fmt.Fprintln(w, "Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':")
			fmt.Fprintln(tabw, "COMPONENT\tCURRENT\tAVAILABLE")
			firstPrinted := false

			// The map is of the form <old-version>:<node-count>. Here all the keys are put into a slice and sorted
			// in order to always get the right order. Then the map value is extracted separately
			for _, oldVersion := range sortedSliceFromStringIntMap(upgrade.Before.KubeletVersions) {
				nodeCount := upgrade.Before.KubeletVersions[oldVersion]
				if !firstPrinted {
					// Output the Kubelet header only on the first version pair
					fmt.Fprintf(tabw, "Kubelet\t%d x %s\t%s\n", nodeCount, oldVersion, upgrade.After.KubeVersion)
					firstPrinted = true
					continue
				}
				fmt.Fprintf(tabw, "\t%d x %s\t%s\n", nodeCount, oldVersion, upgrade.After.KubeVersion)
			}
			// We should flush the writer here at this stage; as the columns will now be of the right size, adjusted to the above content
			tabw.Flush()
			fmt.Fprintln(w, "")
		}

		fmt.Fprintf(w, "Upgrade to the latest %s:\n", upgrade.Description)
		fmt.Fprintln(w, "")
		fmt.Fprintln(tabw, "COMPONENT\tCURRENT\tAVAILABLE")
		fmt.Fprintf(tabw, "API Server\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
		fmt.Fprintf(tabw, "Controller Manager\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
		fmt.Fprintf(tabw, "Scheduler\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
		fmt.Fprintf(tabw, "Kube Proxy\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)

		// TODO There is currently no way to cleanly output upgrades that involve adding, removing, or changing components
		// https://github.com/kubernetes/kubeadm/issues/810 was created to track addressing this.
		printCoreDNS, printKubeDNS := false, false
		coreDNSBeforeVersion, coreDNSAfterVersion, kubeDNSBeforeVersion, kubeDNSAfterVersion := "", "", "", ""

		switch upgrade.Before.DNSType {
		case kubeadmapi.CoreDNS:
			printCoreDNS = true
			coreDNSBeforeVersion = upgrade.Before.DNSVersion
		case kubeadmapi.KubeDNS:
			printKubeDNS = true
			kubeDNSBeforeVersion = upgrade.Before.DNSVersion
		}

		switch upgrade.After.DNSType {
		case kubeadmapi.CoreDNS:
			printCoreDNS = true
			coreDNSAfterVersion = upgrade.After.DNSVersion
		case kubeadmapi.KubeDNS:
			printKubeDNS = true
			kubeDNSAfterVersion = upgrade.After.DNSVersion
		}

		if printCoreDNS {
			fmt.Fprintf(tabw, "CoreDNS\t%s\t%s\n", coreDNSBeforeVersion, coreDNSAfterVersion)
		}
		if printKubeDNS {
			fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", kubeDNSBeforeVersion, kubeDNSAfterVersion)
		}

		if !isExternalEtcd {
			fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion)
		}

		// The tabwriter should be flushed at this stage as we have now put in all the required content for this time. This is required for the tabs' size to be correct.
		tabw.Flush()
		fmt.Fprintln(w, "")
		fmt.Fprintln(w, "You can now apply the upgrade by executing the following command:")
		fmt.Fprintln(w, "")
		fmt.Fprintf(w, "\tkubeadm upgrade apply %s%s\n", upgrade.After.KubeVersion, UnstableVersionFlag)
		fmt.Fprintln(w, "")

		if upgrade.Before.KubeadmVersion != upgrade.After.KubeadmVersion {
			fmt.Fprintf(w, "Note: Before you can perform this upgrade, you have to update kubeadm to %s.\n", upgrade.After.KubeadmVersion)
			fmt.Fprintln(w, "")
		}

		fmt.Fprintln(w, "_____________________________________________________________________")
		fmt.Fprintln(w, "")
	}
}

// sortedSliceFromStringIntMap returns a slice of the keys in the map sorted alphabetically
func sortedSliceFromStringIntMap(strMap map[string]uint16) []string {
	strSlice := []string{}
	for k := range strMap {
		strSlice = append(strSlice, k)
	}
	sort.Strings(strSlice)
	return strSlice
}
<|endoftext|>


<commit_before>package dev

import (
	"github.com/relab/gorums"
)

// A Configuration represents a static set of nodes on which quorum remote
// procedure calls may be invoked.
type Configuration struct {
	gorums.RawConfiguration
	qspec QuorumSpec
}

// Nodes returns a slice of each available node. IDs are returned in the same
// order as they were provided in the creation of the Manager.
func (c *Configuration) Nodes() []*Node {
	nodes := make([]*Node, 0, c.Size())
	for _, n := range c.RawConfiguration {
		nodes = append(nodes, &Node{n})
	}
	return nodes
}

// And returns a NodeListOption that can be used to create a new configuration combining c and d.
func (c Configuration) And(d *Configuration) gorums.NodeListOption {
	return c.RawConfiguration.And(d.RawConfiguration)
}

// Except returns a NodeListOption that can be used to create a new configuration
// from c without the nodes in rm.
func (c Configuration) Except(rm *Configuration) gorums.NodeListOption {
	return c.RawConfiguration.Except(rm.RawConfiguration)
}
<commit_msg>add a ConfigurationFromRaw function<commit_after>package dev

import (
	"github.com/relab/gorums"
)

// A Configuration represents a static set of nodes on which quorum remote
// procedure calls may be invoked.
type Configuration struct {
	gorums.RawConfiguration
	qspec QuorumSpec
}

// ConfigurationFromRaw returns a new Configuration from the given raw configuration and QuorumSpec.
//
// This function may for example be used to "clone" a configuration but install a different QuorumSpec:
//  cfg1, err := mgr.NewConfiguration(qspec1, opts...)
//  cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2)
func ConfigurationFromRaw(rawCfg gorums.RawConfiguration, qspec QuorumSpec) *Configuration {
	// return an error if the QuorumSpec interface is not empty and no implementation was provided.
	var test interface{} = struct{}{}
	if _, empty := test.(QuorumSpec); !empty && qspec == nil {
		panic("QuorumSpec may not be nil")
	}
	return &Configuration{
		RawConfiguration: rawCfg,
		qspec:            qspec,
	}
}

// Nodes returns a slice of each available node. IDs are returned in the same
// order as they were provided in the creation of the Manager.
func (c *Configuration) Nodes() []*Node {
	nodes := make([]*Node, 0, c.Size())
	for _, n := range c.RawConfiguration {
		nodes = append(nodes, &Node{n})
	}
	return nodes
}

// And returns a NodeListOption that can be used to create a new configuration combining c and d.
func (c Configuration) And(d *Configuration) gorums.NodeListOption {
	return c.RawConfiguration.And(d.RawConfiguration)
}

// Except returns a NodeListOption that can be used to create a new configuration
// from c without the nodes in rm.
func (c Configuration) Except(rm *Configuration) gorums.NodeListOption {
	return c.RawConfiguration.Except(rm.RawConfiguration)
}
<|endoftext|>


<commit_before>package serve

import (
	"errors"
	"log"
	"net/http"
)

type recoverHandler struct {
	Action func(error)
	next   http.Handler
}

func (h *recoverHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var err error
	defer func() {
		r := recover()
		if r != nil {
			switch t := r.(type) {
			case string:
				err = errors.New(t)
			case error:
				err = t
			default:
				err = errors.New("Unknown error")
			}

			h.Action(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}()
	h.next.ServeHTTP(w, r)
}

func Recover(h http.Handler) http.Handler {
	return &RecoverHandler{
		Action: log.Println,
		next:   h,
	}
}
<commit_msg>Fix name usage<commit_after>package serve

import (
	"errors"
	"log"
	"net/http"
)

type recoverHandler struct {
	Action func(error)
	next   http.Handler
}

func (h *recoverHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var err error
	defer func() {
		r := recover()
		if r != nil {
			switch t := r.(type) {
			case string:
				err = errors.New(t)
			case error:
				err = t
			default:
				err = errors.New("Unknown error")
			}

			h.Action(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}()
	h.next.ServeHTTP(w, r)
}

func Recover(h http.Handler) http.Handler {
	return &recoverHandler{
		Action: log.Println,
		next:   h,
	}
}
<|endoftext|>


<commit_before>package summa

import (
	"bytes"
	"crypto/sha1"
	"database/sql"
	"encoding/binary"
	"fmt"
	_ "go-sqlite3"
	"math/rand"
	"time"
)

// sessionIsValid checks to determine if a given username and token
// combine to make a valid session
func sessionIsValid(db *sql.DB, username, token string) (bool, error) {
	expired := UnixMilliseconds() - config.SessionExpire

	// Remove expired sessions
	_, err := db.Exec(
		"DELETE FROM user_session WHERE timestamp <= ?",
		expired,
	)
	if err != nil {
		return false, err
	}

	row := db.QueryRow(
		"SELECT COUNT(*) FROM user_session WHERE username=? AND token=?",
		username,
		token,
	)

	var count int64
	err = row.Scan(&count)
	if err != nil {
		return false, err
	}

	return count != 0, nil
}

// sessionCreate generates a random session token for
// a given username and stores it in the database
func sessionCreate(db *sql.DB, username string) (string, error) {
	rand.Seed(time.Now().UnixNano())
	buf := new(bytes.Buffer)
	binary.Write(buf, binary.LittleEndian, rand.Int63())

	hasher := sha1.New()
	hasher.Write(buf.Bytes())
	hasher.Write([]byte(username))

	token := fmt.Sprintf("%x", hasher.Sum(nil))

	_, err := db.Exec(
		"REPLACE INTO user_session VALUES (?,?,?)",
		username,
		token,
		UnixMilliseconds(),
	)

	return token, err
}

// sessionRemove removes a session with a given username
// and token from the database
func sessionRemove(db *sql.DB, username, token string) error {
	_, err := db.Exec(
		"DELETE FROM user_session WHERE username=? AND token=?",
		username,
		token,
	)

	return err
}
<commit_msg>Fix query on invalid column in sessionIsValid<commit_after>package summa

import (
	"bytes"
	"crypto/sha1"
	"database/sql"
	"encoding/binary"
	"fmt"
	_ "go-sqlite3"
	"math/rand"
	"time"
)

// sessionIsValid checks to determine if a given username and token
// combine to make a valid session
func sessionIsValid(db *sql.DB, username, token string) (bool, error) {
	expired := UnixMilliseconds() - config.SessionExpire

	// Remove expired sessions
	_, err := db.Exec(
		"DELETE FROM user_session WHERE created <= ?",
		expired,
	)
	if err != nil {
		return false, err
	}

	row := db.QueryRow(
		"SELECT COUNT(*) FROM user_session WHERE username=? AND token=?",
		username,
		token,
	)

	var count int64
	err = row.Scan(&count)
	if err != nil {
		return false, err
	}

	return count != 0, nil
}

// sessionCreate generates a random session token for
// a given username and stores it in the database
func sessionCreate(db *sql.DB, username string) (string, error) {
	rand.Seed(time.Now().UnixNano())
	buf := new(bytes.Buffer)
	binary.Write(buf, binary.LittleEndian, rand.Int63())

	hasher := sha1.New()
	hasher.Write(buf.Bytes())
	hasher.Write([]byte(username))

	token := fmt.Sprintf("%x", hasher.Sum(nil))

	_, err := db.Exec(
		"REPLACE INTO user_session VALUES (?,?,?)",
		username,
		token,
		UnixMilliseconds(),
	)

	return token, err
}

// sessionRemove removes a session with a given username
// and token from the database
func sessionRemove(db *sql.DB, username, token string) error {
	_, err := db.Exec(
		"DELETE FROM user_session WHERE username=? AND token=?",
		username,
		token,
	)

	return err
}
<|endoftext|>


<commit_before>// Copyright 2020 The LUCI 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 lib

import (
	"context"
	"fmt"

	"github.com/bazelbuild/remote-apis-sdks/go/pkg/chunker"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/command"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/filemetadata"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/tree"
	"github.com/maruel/subcommands"

	"go.chromium.org/luci/client/isolated"
	"go.chromium.org/luci/common/cli"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/system/signals"
)

// CmdArchive returns an object for the `archive` subcommand.
func CmdArchive() *subcommands.Command {
	return &subcommands.Command{
		UsageLine: "archive <options>...",
		ShortDesc: "archive files to CAS",
		LongDesc: `Given a list of files and directories, creates a CAS tree and digest file for
that and uploads the tree to the CAS server.

When specifying directories and files, you must also specify a current working
directory for each file and directory. The current working directory will not be
included in the archived path. For example, to archive './usr/foo/bar' and have
it appear as 'foo/bar' in the CAS tree, specify '-files ./usr:foo/bar' or
'-files usr:foo/bar'. When the CAS tree is then downloaded, it will then appear
under 'foo/bar' in the desired directory.

Note that '.' may be omitted in general, so to upload 'foo' from the current
working directory, '-files :foo' is sufficient.`,
		CommandRun: func() subcommands.CommandRun {
			c := archiveRun{}
			c.Init()
			c.Flags.Var(&c.dirs, "dirs", "Directory(ies) to archive. Specify as <working directory>:<relative path to dir>")
			c.Flags.Var(&c.files, "files", "Individual file(s) to archive. Specify as <working directory>:<relative path to file>")
			return &c
		},
	}
}

type archiveRun struct {
	commonFlags
	dirs  isolated.ScatterGather
	files isolated.ScatterGather
}

func (c *archiveRun) Parse(a subcommands.Application, args []string) error {
	if err := c.commonFlags.Parse(); err != nil {
		return err
	}
	if len(args) != 0 {
		return errors.Reason("position arguments not expected").Err()
	}
	return nil
}

// getRoot returns root directory if there is only one working directory.
func getRoot(dirs, files isolated.ScatterGather) (string, error) {
	var rel0, wd0 string
	pickedOne := false
	for rel, wd := range dirs {
		if !pickedOne {
			rel0 = rel
			wd0 = wd
			pickedOne = true
			continue
		}

		if wd0 != wd {
			return "", errors.Reason("different root (working) directory is not supported: %s:%s vs %s:%s", wd0, rel0, wd, rel).Err()
		}
	}

	for rel, wd := range files {
		if !pickedOne {
			rel0 = rel
			wd0 = wd
			pickedOne = true
			continue
		}

		if wd0 != wd {
			return "", errors.Reason("different root (working) directory is not supported: %s:%s vs %s:%s", wd0, rel0, wd, rel).Err()
		}
	}

	if !pickedOne {
		return "", errors.Reason("-dirs or -files should be specified at least once").Err()
	}

	return wd0, nil
}

// Does the archive by uploading to isolate-server, then return the archive stats and error.
func (c *archiveRun) doArchive(ctx context.Context, args []string) error {
	ctx, cancel := context.WithCancel(ctx)
	signals.HandleInterrupt(cancel)

	root, err := getRoot(c.dirs, c.files)
	if err != nil {
		return err
	}

	is := command.InputSpec{}
	for dir := range c.dirs {
		is.Inputs = append(is.Inputs, dir)
	}
	for file := range c.files {
		is.Inputs = append(is.Inputs, file)
	}

	rootDg, chunkers, _, err := tree.ComputeMerkleTree(root, &is, chunker.DefaultChunkSize, filemetadata.NewNoopCache())
	if err != nil {
		return errors.Annotate(err, "failed to call ComputeMerkleTree").Err()
	}

	client, err := c.casFlags.NewClient(ctx)
	if err != nil {
		return errors.Annotate(err, "failed to create cas client").Err()
	}
	defer client.Close()

	if err := client.UploadIfMissing(ctx, chunkers...); err != nil {
		return errors.Annotate(err, "failed to call UploadIfMissing").Err()
	}

	return c.casFlags.WriteDigest(rootDg)
}

func (c *archiveRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
	ctx := cli.GetContext(a, c, env)

	if err := c.Parse(a, args); err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}

	if err := c.doArchive(ctx, args); err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}

	return 0
}
<commit_msg>cas: fix comment / docs<commit_after>// Copyright 2020 The LUCI 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 lib

import (
	"context"
	"fmt"

	"github.com/bazelbuild/remote-apis-sdks/go/pkg/chunker"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/command"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/filemetadata"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/tree"
	"github.com/maruel/subcommands"

	"go.chromium.org/luci/client/isolated"
	"go.chromium.org/luci/common/cli"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/system/signals"
)

// CmdArchive returns an object for the `archive` subcommand.
func CmdArchive() *subcommands.Command {
	return &subcommands.Command{
		UsageLine: "archive <options>...",
		ShortDesc: "archive files to CAS",
		LongDesc: `Given a list of files and directories, creates a CAS tree and digest file for
that and uploads the tree to the CAS server.

When specifying directories and files, you must also specify a current working
directory for each file and directory. The current working directory will not be
included in the archived path. For example, to archive './usr/foo/bar' and have
it appear as 'foo/bar' in the CAS tree, specify '-files ./usr:foo/bar' or
'-files usr:foo/bar'. And all workind directories should be the same. When the
CAS tree is then downloaded, it will then appear under 'foo/bar' in the desired
directory.

Note that '.' may be omitted in general, so to upload 'foo' from the current
working directory, '-files :foo' is sufficient.`,
		CommandRun: func() subcommands.CommandRun {
			c := archiveRun{}
			c.Init()
			c.Flags.Var(&c.dirs, "dirs", "Directory(ies) to archive. Specify as <working directory>:<relative path to dir>")
			c.Flags.Var(&c.files, "files", "Individual file(s) to archive. Specify as <working directory>:<relative path to file>")
			return &c
		},
	}
}

type archiveRun struct {
	commonFlags
	dirs  isolated.ScatterGather
	files isolated.ScatterGather
}

func (c *archiveRun) Parse(a subcommands.Application, args []string) error {
	if err := c.commonFlags.Parse(); err != nil {
		return err
	}
	if len(args) != 0 {
		return errors.Reason("position arguments not expected").Err()
	}
	return nil
}

// getRoot returns root directory if there is only one working directory.
func getRoot(dirs, files isolated.ScatterGather) (string, error) {
	var rel0, wd0 string
	pickedOne := false
	for rel, wd := range dirs {
		if !pickedOne {
			rel0 = rel
			wd0 = wd
			pickedOne = true
			continue
		}

		if wd0 != wd {
			return "", errors.Reason("different root (working) directory is not supported: %s:%s vs %s:%s", wd0, rel0, wd, rel).Err()
		}
	}

	for rel, wd := range files {
		if !pickedOne {
			rel0 = rel
			wd0 = wd
			pickedOne = true
			continue
		}

		if wd0 != wd {
			return "", errors.Reason("different root (working) directory is not supported: %s:%s vs %s:%s", wd0, rel0, wd, rel).Err()
		}
	}

	if !pickedOne {
		return "", errors.Reason("-dirs or -files should be specified at least once").Err()
	}

	return wd0, nil
}

// Does the archive by uploading to isolate-server.
func (c *archiveRun) doArchive(ctx context.Context, args []string) error {
	ctx, cancel := context.WithCancel(ctx)
	signals.HandleInterrupt(cancel)

	root, err := getRoot(c.dirs, c.files)
	if err != nil {
		return err
	}

	is := command.InputSpec{}
	for dir := range c.dirs {
		is.Inputs = append(is.Inputs, dir)
	}
	for file := range c.files {
		is.Inputs = append(is.Inputs, file)
	}

	rootDg, chunkers, _, err := tree.ComputeMerkleTree(root, &is, chunker.DefaultChunkSize, filemetadata.NewNoopCache())
	if err != nil {
		return errors.Annotate(err, "failed to call ComputeMerkleTree").Err()
	}

	client, err := c.casFlags.NewClient(ctx)
	if err != nil {
		return errors.Annotate(err, "failed to create cas client").Err()
	}
	defer client.Close()

	if err := client.UploadIfMissing(ctx, chunkers...); err != nil {
		return errors.Annotate(err, "failed to call UploadIfMissing").Err()
	}

	return c.casFlags.WriteDigest(rootDg)
}

func (c *archiveRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
	ctx := cli.GetContext(a, c, env)

	if err := c.Parse(a, args); err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}

	if err := c.doArchive(ctx, args); err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}

	return 0
}
<|endoftext|>


<commit_before>package mfsr

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

const VersionFile = "version"

type RepoPath string

func (rp RepoPath) VersionFile() string {
	return path.Join(string(rp), VersionFile)
}

func (rp RepoPath) Version() (int, error) {
	if rp == "" {
		return 0, fmt.Errorf("invalid repo path \"%s\"", rp)
	}

	fn := rp.VersionFile()
	if _, err := os.Stat(fn); err != nil {
		return 0, err
	}

	c, err := ioutil.ReadFile(fn)
	if err != nil {
		return 0, err
	}

	s := strings.TrimSpace(string(c))
	return strconv.Atoi(s)
}

func (rp RepoPath) CheckVersion(version int) error {
	v, err := rp.Version()
	if err != nil {
		return err
	}

	if v != version {
		return fmt.Errorf("versions differ (expected: %s, actual:%s)", version, v)
	}

	return nil
}

func (rp RepoPath) WriteVersion(version int) error {
	fn := rp.VersionFile()
	return ioutil.WriteFile(fn, []byte(fmt.Sprintf("%d\n", version)), 0644)
}
<commit_msg>Cleanup go vet error<commit_after>package mfsr

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

const VersionFile = "version"

type RepoPath string

func (rp RepoPath) VersionFile() string {
	return path.Join(string(rp), VersionFile)
}

func (rp RepoPath) Version() (int, error) {
	if rp == "" {
		return 0, fmt.Errorf("invalid repo path \"%s\"", rp)
	}

	fn := rp.VersionFile()
	if _, err := os.Stat(fn); err != nil {
		return 0, err
	}

	c, err := ioutil.ReadFile(fn)
	if err != nil {
		return 0, err
	}

	s := strings.TrimSpace(string(c))
	return strconv.Atoi(s)
}

func (rp RepoPath) CheckVersion(version int) error {
	v, err := rp.Version()
	if err != nil {
		return err
	}

	if v != version {
		return fmt.Errorf("versions differ (expected: %d, actual:%d)", version, v)
	}

	return nil
}

func (rp RepoPath) WriteVersion(version int) error {
	fn := rp.VersionFile()
	return ioutil.WriteFile(fn, []byte(fmt.Sprintf("%d\n", version)), 0644)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/olivere/elastic"
	"log"
	"net/http"
	_ "net/http/httputil"
	"os"
	"time"
)

var cmdReindex = &Command{
	Run:   runReindex,
	Usage: "reindex [-v] <source> <target>",
	Short: "reindex one index to another index",
	Long: `
The reindex command takes the documents from the source index
and bulk imports them to the specified target index.

This is quite handy if you want to change the settings of an
index and won't lose any data.

Use the -v/--verbose flag to print progress.

Example:

  $ es reindex -v twitter twitter-snapshot
`,
	ApiUrl: "http://www.elasticsearch.org/guide/reference/api/bulk.html",
}

func init() {
	cmdReindex.Flag.BoolVar(&verbose, "v", false, "verbose")
}

func runReindex(cmd *Command, args []string) {
	if len(args) < 2 {
		cmd.printUsage()
		os.Exit(1)
	}

	source := args[0]
	target := args[1]

	// Get a client
	client, err := elastic.NewClient(http.DefaultClient, esUrl)
	if err != nil {
		log.Fatal("Error: %v", err)
	}

	// Create target index, if not already exists
	exists, err := client.IndexExists(target).Do()
	if err != nil {
		log.Fatal("Error: %v", err)
	}
	if !exists {
		_, err := client.CreateIndex(target).Do()
		if err != nil {
			log.Fatal("Error: %v", err)
		}

		// Flush
		client.Flush().Index(target).Do()
	}

	// Scan through source
	bulkSize := 1000
	bulk := client.Bulk().Index(target).DebugOnError(true)
	inserted := 0

	cursor, err := client.Scan(source).Do()
	if err != nil {
		log.Fatal("Error: %v", err)
	}

	// Iterate
	for {
		sr, err := cursor.Next()
		if err == elastic.EOS {
			break
		}
		if err != nil {
			log.Fatal("Error: %v", err)
		}

		if sr.Hits != nil && sr.Hits.Hits != nil {
			for _, hit := range sr.Hits.Hits {
				indexReq := &elastic.BulkIndexRequest{
					Id:   hit.Id,
					Type: hit.Type,
					Data: string(*hit.Source),
				}
				bulk.Add(indexReq)

				inserted += 1

				if verbose {
					fmt.Fprintf(os.Stderr, "Reindexing %9d\r", inserted)
				}

				if bulk.NumberOfActions() >= bulkSize {
					bulk, err = commitBulk(client, bulk, target)
					if err != nil {
						log.Fatal("Error: %v", err)
					}
				}
			}
		}
	}

	if bulk.NumberOfActions() > 0 {
		bulk, err = commitBulk(client, bulk, target)
		if err != nil {
			log.Fatal("Error: %v", err)
		}
	}

	// Flush
	_, err = client.Flush().Index(target).Do()
	if err != nil {
		log.Fatal("Error: %v", err)
	}

	if verbose {
		fmt.Fprintf(os.Stderr, "Reindexed %9d    \n", inserted)
	}
}

// commitBulk commits the bulk actions to Elasticsearch. When an error
// occurs, it retries the bulk operation several times before failing.
func commitBulk(client *elastic.Client, bulk *elastic.BulkService, indexName string) (*elastic.BulkService, error) {
	sleepSeconds := int64(1)
	numRetries := 5

	for {
		_, err := bulk.Do()
		if err != nil {
			numRetries -= 1
			if numRetries < 0 {
				return bulk, err
			}
			time.Sleep(time.Duration(sleepSeconds) * time.Second)
			sleepSeconds *= 2
		} else {
			break
		}
	}

	// Return a new bulk request
	bulk = client.Bulk().Index(indexName).DebugOnError(true)

	return bulk, nil
}
<commit_msg>fix reindex command<commit_after>package main

import (
	"fmt"
	"github.com/olivere/elastic"
	"log"
	"net/http"
	_ "net/http/httputil"
	"os"
	"time"
)

var cmdReindex = &Command{
	Run:   runReindex,
	Usage: "reindex [-v] <source> <target>",
	Short: "reindex one index to another index",
	Long: `
The reindex command takes the documents from the source index
and bulk imports them to the specified target index.

This is quite handy if you want to change the settings of an
index and won't lose any data.

Use the -v/--verbose flag to print progress.

Example:

  $ es reindex -v twitter twitter-snapshot
`,
	ApiUrl: "http://www.elasticsearch.org/guide/reference/api/bulk.html",
}

func init() {
	cmdReindex.Flag.BoolVar(&verbose, "v", false, "verbose")
}

func runReindex(cmd *Command, args []string) {
	if len(args) < 2 {
		cmd.printUsage()
		os.Exit(1)
	}

	source := args[0]
	target := args[1]

	// Get a client
	client, err := elastic.NewClient(http.DefaultClient, esUrl)
	if err != nil {
		log.Fatal("Error: %v", err)
	}

	// Create target index, if not already exists
	exists, err := client.IndexExists(target).Do()
	if err != nil {
		log.Fatal("Error: %v", err)
	}
	if !exists {
		_, err := client.CreateIndex(target).Do()
		if err != nil {
			log.Fatal("Error: %v", err)
		}

		// Flush
		client.Flush().Index(target).Do()
	}

	// Scan through source
	bulkSize := 1000
	bulk := client.Bulk().Index(target).DebugOnError(true)
	inserted := 0

	cursor, err := client.Scan(source).Do()
	if err != nil {
		log.Fatal("Error: %v", err)
	}

	// Iterate
	for {
		sr, err := cursor.Next()
		if err == elastic.EOS {
			break
		}
		if err != nil {
			log.Fatal("Error: %v", err)
		}

		if sr.Hits != nil && sr.Hits.Hits != nil {
			for _, hit := range sr.Hits.Hits {
				indexReq := elastic.NewBulkIndexRequest().
					Id(hit.Id).
					Type(hit.Type).
					Doc(string(*hit.Source))

				bulk.Add(indexReq)

				inserted += 1

				if verbose {
					fmt.Fprintf(os.Stderr, "Reindexing %9d\r", inserted)
				}

				if bulk.NumberOfActions() >= bulkSize {
					bulk, err = commitBulk(client, bulk, target)
					if err != nil {
						log.Fatal("Error: %v", err)
					}
				}
			}
		}
	}

	if bulk.NumberOfActions() > 0 {
		bulk, err = commitBulk(client, bulk, target)
		if err != nil {
			log.Fatal("Error: %v", err)
		}
	}

	// Flush
	_, err = client.Flush().Index(target).Do()
	if err != nil {
		log.Fatal("Error: %v", err)
	}

	if verbose {
		fmt.Fprintf(os.Stderr, "Reindexed %9d    \n", inserted)
	}
}

// commitBulk commits the bulk actions to Elasticsearch. When an error
// occurs, it retries the bulk operation several times before failing.
func commitBulk(client *elastic.Client, bulk *elastic.BulkService, indexName string) (*elastic.BulkService, error) {
	sleepSeconds := int64(1)
	numRetries := 5

	for {
		_, err := bulk.Do()
		if err != nil {
			numRetries -= 1
			if numRetries < 0 {
				return bulk, err
			}
			time.Sleep(time.Duration(sleepSeconds) * time.Second)
			sleepSeconds *= 2
		} else {
			break
		}
	}

	// Return a new bulk request
	bulk = client.Bulk().Index(indexName).DebugOnError(true)

	return bulk, nil
}
<|endoftext|>


<commit_before>package internal

import (
	"github.com/cloudfoundry-incubator/bbs/models"
	"github.com/cloudfoundry-incubator/executor"
	"github.com/cloudfoundry-incubator/rep"

	"github.com/cloudfoundry-incubator/bbs"
	"github.com/pivotal-golang/lager"
)

const TaskCompletionReasonMissingContainer = "task container does not exist"
const TaskCompletionReasonFailedToRunContainer = "failed to run container"
const TaskCompletionReasonInvalidTransition = "invalid state transition"
const TaskCompletionReasonFailedToFetchResult = "failed to fetch result"

//go:generate counterfeiter -o fake_internal/fake_task_processor.go task_processor.go TaskProcessor

type TaskProcessor interface {
	Process(lager.Logger, executor.Container)
}

type taskProcessor struct {
	bbsClient         bbs.Client
	containerDelegate ContainerDelegate
	cellID            string
}

func NewTaskProcessor(bbs bbs.Client, containerDelegate ContainerDelegate, cellID string) TaskProcessor {
	return &taskProcessor{
		bbsClient:         bbs,
		containerDelegate: containerDelegate,
		cellID:            cellID,
	}
}

func (p *taskProcessor) Process(logger lager.Logger, container executor.Container) {
	logger = logger.Session("task-processor", lager.Data{
		"container-guid":  container.Guid,
		"container-state": container.State,
	})

	logger.Debug("starting")
	defer logger.Debug("finished")

	switch container.State {
	case executor.StateReserved:
		logger.Debug("processing-reserved-container")
		p.processActiveContainer(logger, container)
	case executor.StateInitializing:
		logger.Debug("processing-initializing-container")
		p.processActiveContainer(logger, container)
	case executor.StateCreated:
		logger.Debug("processing-created-container")
		p.processActiveContainer(logger, container)
	case executor.StateRunning:
		logger.Debug("processing-running-container")
		p.processActiveContainer(logger, container)
	case executor.StateCompleted:
		logger.Debug("processing-completed-container")
		p.processCompletedContainer(logger, container)
	}
}

func (p *taskProcessor) processActiveContainer(logger lager.Logger, container executor.Container) {
	ok := p.startTask(logger, container.Guid)
	if !ok {
		return
	}

	ok = p.containerDelegate.RunContainer(logger, container.Guid)
	if !ok {
		p.failTask(logger, container.Guid, TaskCompletionReasonFailedToRunContainer)
	}
}

func (p *taskProcessor) processCompletedContainer(logger lager.Logger, container executor.Container) {
	p.completeTask(logger, container)
	p.containerDelegate.DeleteContainer(logger, container.Guid)
}

func (p *taskProcessor) startTask(logger lager.Logger, guid string) bool {
	logger.Info("starting-task")
	changed, err := p.bbsClient.StartTask(guid, p.cellID)
	if err != nil {
		logger.Error("failed-starting-task", err)

		if mErr, ok := err.(*models.Error); ok {
			if mErr.Type == models.InvalidStateTransition {
				p.containerDelegate.DeleteContainer(logger, guid)
			} else if mErr.Equal(models.ErrResourceNotFound) {
				p.containerDelegate.DeleteContainer(logger, guid)
			}
		}
		return false
	}

	if changed {
		logger.Info("succeeded-starting-task")
	} else {
		logger.Info("task-already-started")
	}

	return changed
}

func (p *taskProcessor) completeTask(logger lager.Logger, container executor.Container) {
	var result string
	var err error
	if !container.RunResult.Failed {
		result, err = p.containerDelegate.FetchContainerResultFile(logger, container.Guid, container.Tags[rep.ResultFileTag])
		if err != nil {
			p.failTask(logger, container.Guid, TaskCompletionReasonFailedToFetchResult)
			return
		}
	}

	logger.Info("completing-task")
	err = p.bbsClient.CompleteTask(container.Guid, p.cellID, container.RunResult.Failed, container.RunResult.FailureReason, result)
	if err != nil {
		logger.Error("failed-completing-task", err)

		if modelErr, ok := err.(*models.Error); ok {
			if modelErr.Type == models.InvalidStateTransition {
				p.failTask(logger, container.Guid, TaskCompletionReasonInvalidTransition)
			}
		}
		return
	}

	logger.Info("succeeded-completing-task")
}

func (p *taskProcessor) failTask(logger lager.Logger, guid string, reason string) {
	logger.Info("failing-task")
	err := p.bbsClient.FailTask(guid, reason)
	if err != nil {
		logger.Error("failed-failing-task", err)
		return
	}

	logger.Info("succeeded-failing-task")
}
<commit_msg>Use new bbs model error type enum<commit_after>package internal

import (
	"github.com/cloudfoundry-incubator/bbs/models"
	"github.com/cloudfoundry-incubator/executor"
	"github.com/cloudfoundry-incubator/rep"

	"github.com/cloudfoundry-incubator/bbs"
	"github.com/pivotal-golang/lager"
)

const TaskCompletionReasonMissingContainer = "task container does not exist"
const TaskCompletionReasonFailedToRunContainer = "failed to run container"
const TaskCompletionReasonInvalidTransition = "invalid state transition"
const TaskCompletionReasonFailedToFetchResult = "failed to fetch result"

//go:generate counterfeiter -o fake_internal/fake_task_processor.go task_processor.go TaskProcessor

type TaskProcessor interface {
	Process(lager.Logger, executor.Container)
}

type taskProcessor struct {
	bbsClient         bbs.Client
	containerDelegate ContainerDelegate
	cellID            string
}

func NewTaskProcessor(bbs bbs.Client, containerDelegate ContainerDelegate, cellID string) TaskProcessor {
	return &taskProcessor{
		bbsClient:         bbs,
		containerDelegate: containerDelegate,
		cellID:            cellID,
	}
}

func (p *taskProcessor) Process(logger lager.Logger, container executor.Container) {
	logger = logger.Session("task-processor", lager.Data{
		"container-guid":  container.Guid,
		"container-state": container.State,
	})

	logger.Debug("starting")
	defer logger.Debug("finished")

	switch container.State {
	case executor.StateReserved:
		logger.Debug("processing-reserved-container")
		p.processActiveContainer(logger, container)
	case executor.StateInitializing:
		logger.Debug("processing-initializing-container")
		p.processActiveContainer(logger, container)
	case executor.StateCreated:
		logger.Debug("processing-created-container")
		p.processActiveContainer(logger, container)
	case executor.StateRunning:
		logger.Debug("processing-running-container")
		p.processActiveContainer(logger, container)
	case executor.StateCompleted:
		logger.Debug("processing-completed-container")
		p.processCompletedContainer(logger, container)
	}
}

func (p *taskProcessor) processActiveContainer(logger lager.Logger, container executor.Container) {
	ok := p.startTask(logger, container.Guid)
	if !ok {
		return
	}

	ok = p.containerDelegate.RunContainer(logger, container.Guid)
	if !ok {
		p.failTask(logger, container.Guid, TaskCompletionReasonFailedToRunContainer)
	}
}

func (p *taskProcessor) processCompletedContainer(logger lager.Logger, container executor.Container) {
	p.completeTask(logger, container)
	p.containerDelegate.DeleteContainer(logger, container.Guid)
}

func (p *taskProcessor) startTask(logger lager.Logger, guid string) bool {
	logger.Info("starting-task")
	changed, err := p.bbsClient.StartTask(guid, p.cellID)
	if err != nil {
		logger.Error("failed-starting-task", err)

		if mErr, ok := err.(*models.Error); ok {
			if mErr.Type == models.Error_InvalidStateTransition {
				p.containerDelegate.DeleteContainer(logger, guid)
			} else if mErr.Equal(models.ErrResourceNotFound) {
				p.containerDelegate.DeleteContainer(logger, guid)
			}
		}
		return false
	}

	if changed {
		logger.Info("succeeded-starting-task")
	} else {
		logger.Info("task-already-started")
	}

	return changed
}

func (p *taskProcessor) completeTask(logger lager.Logger, container executor.Container) {
	var result string
	var err error
	if !container.RunResult.Failed {
		result, err = p.containerDelegate.FetchContainerResultFile(logger, container.Guid, container.Tags[rep.ResultFileTag])
		if err != nil {
			p.failTask(logger, container.Guid, TaskCompletionReasonFailedToFetchResult)
			return
		}
	}

	logger.Info("completing-task")
	err = p.bbsClient.CompleteTask(container.Guid, p.cellID, container.RunResult.Failed, container.RunResult.FailureReason, result)
	if err != nil {
		logger.Error("failed-completing-task", err)

		if modelErr, ok := err.(*models.Error); ok {
			if modelErr.Type == models.Error_InvalidStateTransition {
				p.failTask(logger, container.Guid, TaskCompletionReasonInvalidTransition)
			}
		}
		return
	}

	logger.Info("succeeded-completing-task")
}

func (p *taskProcessor) failTask(logger lager.Logger, guid string, reason string) {
	logger.Info("failing-task")
	err := p.bbsClient.FailTask(guid, reason)
	if err != nil {
		logger.Error("failed-failing-task", err)
		return
	}

	logger.Info("succeeded-failing-task")
}
<|endoftext|>


<commit_before>// Copyright 2019, OpenCensus 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 resourcekeys contains well known type and label keys for resources.
package resourcekeys // import "go.opencensus.io/resource/resourcekeys"

// Constants for Kubernetes resources.
const (
	K8SType = "k8s"

	// A uniquely identifying name for the Kubernetes cluster. Kubernetes
	// does not have cluster names as an internal concept so this may be
	// set to any meaningful value within the environment. For example,
	// GKE clusters have a name which can be used for this label.
	K8SKeyClusterName   = "k8s.cluster.name"
	K8SKeyNamespaceName = "k8s.namespace.name"
	K8SKeyPodName       = "k8s.pod.name"
)

// Constants for Container resources.
const (
	ContainerType = "container"

	// A uniquely identifying name for the Container.
	ContainerKeyName      = "container.name"
	ContainerKeyImageName = "container.image.name"
	ContainerKeyImageTag  = "container.image.tag"
)

// Constants for Cloud resources.
const (
	CloudType = "cloud"

	CloudKeyProvider  = "cloud.provider"
	CloudKeyAccountID = "cloud.account.id"
	CloudKeyRegion    = "cloud.region"
	CloudKeyZone      = "cloud.zone"

	// Cloud Providers
	CloudProviderAWS   = "aws"
	CloudProviderGCP   = "gcp"
	CloudProviderAZURE = "azure"
)

// Constants for Host resources.
const (
	HostType = "host"

	// A uniquely identifying name for the host.
	HostKeyName = "host.name"

	// A hostname as returned by the 'hostname' command on host machine.
	HostKeyHostName = "host.hostname"
	HostKeyID       = "host.id"
	HostKeyType     = "host.type"
)
<commit_msg>Add deployment key for k8s resource. (#1148)<commit_after>// Copyright 2019, OpenCensus 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 resourcekeys contains well known type and label keys for resources.
package resourcekeys // import "go.opencensus.io/resource/resourcekeys"

// Constants for Kubernetes resources.
const (
	K8SType = "k8s"

	// A uniquely identifying name for the Kubernetes cluster. Kubernetes
	// does not have cluster names as an internal concept so this may be
	// set to any meaningful value within the environment. For example,
	// GKE clusters have a name which can be used for this label.
	K8SKeyClusterName    = "k8s.cluster.name"
	K8SKeyNamespaceName  = "k8s.namespace.name"
	K8SKeyPodName        = "k8s.pod.name"
	K8SKeyDeploymentName = "k8s.deployment.name"
)

// Constants for Container resources.
const (
	ContainerType = "container"

	// A uniquely identifying name for the Container.
	ContainerKeyName      = "container.name"
	ContainerKeyImageName = "container.image.name"
	ContainerKeyImageTag  = "container.image.tag"
)

// Constants for Cloud resources.
const (
	CloudType = "cloud"

	CloudKeyProvider  = "cloud.provider"
	CloudKeyAccountID = "cloud.account.id"
	CloudKeyRegion    = "cloud.region"
	CloudKeyZone      = "cloud.zone"

	// Cloud Providers
	CloudProviderAWS   = "aws"
	CloudProviderGCP   = "gcp"
	CloudProviderAZURE = "azure"
)

// Constants for Host resources.
const (
	HostType = "host"

	// A uniquely identifying name for the host.
	HostKeyName = "host.name"

	// A hostname as returned by the 'hostname' command on host machine.
	HostKeyHostName = "host.hostname"
	HostKeyID       = "host.id"
	HostKeyType     = "host.type"
)
<|endoftext|>