<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsfake

import (
	"errors"
	"fmt"
	"io"
	"sort"
	"strings"
	"unicode/utf8"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

// Create an in-memory bucket with the given name and empty contents.
func NewFakeBucket(name string) gcs.Bucket {
	b := &bucket{name: name}
	b.mu = syncutil.NewInvariantMutex(func() { b.checkInvariants() })
	return b
}

type object struct {
	// A storage.Object representing metadata for this object. Never changes.
	metadata *storage.Object

	// The contents of the object. These never change.
	contents []byte
}

// A slice of objects compared by name.
type objectSlice []object

func (s objectSlice) Len() int           { return len(s) }
func (s objectSlice) Less(i, j int) bool { return s[i].metadata.Name < s[j].metadata.Name }
func (s objectSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

// Return the smallest i such that s[i].metadata.Name >= name, or len(s) if
// there is no such i.
func (s objectSlice) lowerBound(name string) int {
	pred := func(i int) bool {
		return s[i].metadata.Name >= name
	}

	return sort.Search(len(s), pred)
}

// Return the smallest i such that s[i].metadata.Name == name, or len(s) if
// there is no such i.
func (s objectSlice) find(name string) int {
	lb := s.lowerBound(name)
	if lb < len(s) && s[lb].metadata.Name == name {
		return lb
	}

	return len(s)
}

// Return the smallest string that is lexicographically larger than prefix and
// does not have prefix as a prefix. For the sole case where this is not
// possible (all strings consisting solely of 0xff bytes, including the empty
// string), return the empty string.
func prefixSuccessor(prefix string) string {
	// Attempt to increment the last byte. If that is a 0xff byte, erase it and
	// recurse. If we hit an empty string, then we know our task is impossible.
	limit := []byte(prefix)
	for len(limit) > 0 {
		b := limit[len(limit)-1]
		if b != 0xff {
			limit[len(limit)-1]++
			break
		}

		limit = limit[:len(limit)-1]
	}

	return string(limit)
}

// Return the smallest i such that prefix < s[i].metadata.Name and
// !strings.HasPrefix(s[i].metadata.Name, prefix).
func (s objectSlice) prefixUpperBound(prefix string) int {
	successor := prefixSuccessor(prefix)
	if successor == "" {
		return len(s)
	}

	return s.lowerBound(successor)
}

type bucket struct {
	name string
	mu   syncutil.InvariantMutex

	// The set of extant objects.
	//
	// INVARIANT: Strictly increasing.
	objects objectSlice // GUARDED_BY(mu)
}

// SHARED_LOCKS_REQUIRED(b.mu)
func (b *bucket) checkInvariants() {
	// Make sure 'objects' is strictly increasing.
	for i := 1; i < len(b.objects); i++ {
		objA := b.objects[i-1]
		objB := b.objects[i]
		if !(objA.metadata.Name < objB.metadata.Name) {
			panic(
				fmt.Sprintf(
					"Object names are not strictly increasing: %v vs. %v",
					objA.metadata.Name,
					objB.metadata.Name))
		}
	}
}

func (b *bucket) Name() string {
	return b.name
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) ListObjects(
	ctx context.Context,
	query *storage.Query) (listing *storage.Objects, err error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	// Set up the result object.
	listing = new(storage.Objects)

	// Handle nil queries.
	if query == nil {
		query = &storage.Query{}
	}

	// Handle defaults.
	maxResults := query.MaxResults
	if maxResults == 0 {
		maxResults = 1000
	}

	// Find where in the space of object names to start.
	nameStart := query.Prefix
	if query.Cursor != "" && query.Cursor > nameStart {
		nameStart = query.Cursor
	}

	// Find the range of indexes within the array to scan.
	indexStart := b.objects.lowerBound(nameStart)
	prefixLimit := b.objects.prefixUpperBound(query.Prefix)
	indexLimit := minInt(indexStart+maxResults, prefixLimit)

	// Scan the array.
	var lastResultWasPrefix bool
	for i := indexStart; i < indexLimit; i++ {
		var o object = b.objects[i]
		name := o.metadata.Name

		// Search for a delimiter if necessary.
		if query.Delimiter != "" {
			// Search only in the part after the prefix.
			nameMinusQueryPrefix := name[len(query.Prefix):]

			delimiterIndex := strings.IndexAny(nameMinusQueryPrefix, query.Delimiter)
			if delimiterIndex >= 0 {
				resultPrefixLimit := delimiterIndex

				// Transform to an index within name.
				resultPrefixLimit += len(query.Prefix)

				// Include the delimiter in the result.
				resultPrefixLimit += len(query.Delimiter)

				// Save the result, but only if it's not a duplicate.
				resultPrefix := name[:resultPrefixLimit]
				if len(listing.Prefixes) == 0 ||
					listing.Prefixes[len(listing.Prefixes)-1] != resultPrefix {
					listing.Prefixes = append(listing.Prefixes, resultPrefix)
				}

				lastResultWasPrefix = true
				continue
			}
		}

		lastResultWasPrefix = false

		// Otherwise, save as an object result.
		listing.Results = append(listing.Results, o.metadata)
	}

	// Set up a cursor for where to start the next scan if we didn't exhaust the
	// results.
	if indexLimit < prefixLimit {
		listing.Next = &storage.Query{}
		*listing.Next = *query

		// Ion is if the final object we visited was returned as an element in
		// listing.Prefixes, we want to skip all other objects that would result in
		// the same so we don't return duplicate elements in listing.Prefixes
		// accross requests.
		if lastResultWasPrefix {
			lastResultPrefix := listing.Prefixes[len(listing.Prefixes)-1]
			listing.Next.Cursor = prefixSuccessor(lastResultPrefix)

			// Check an assumption: prefixSuccessor cannot result in the empty string
			// above because object names must be non-empty UTF-8 strings, and there
			// is no valid non-empty UTF-8 string that consists of entirely 0xff
			// bytes.
			if listing.Next.Cursor == "" {
				err = errors.New("Unexpected empty string from prefixSuccessor")
				return
			}
		} else {
			// Otherwise, we'll start scanning at the next object.
			listing.Next.Cursor = b.objects[indexLimit].metadata.Name
		}
	}

	return
}

func (b *bucket) NewReader(
	ctx context.Context,
	objectName string) (io.ReadCloser, error) {
	return nil, errors.New("TODO: Implement NewReader.")
}

func (b *bucket) NewWriter(
	ctx context.Context,
	attrs *storage.ObjectAttrs) (gcs.ObjectWriter, error) {
	// Check that the object name is legal.
	name := attrs.Name
	if len(name) == 0 || len(name) > 1024 {
		return nil, errors.New("Invalid object name: length must be in [1, 1024]")
	}

	if !utf8.ValidString(name) {
		return nil, errors.New("Invalid object name: not valid UTF-8")
	}

	for _, r := range name {
		if r == 0x0a || r == 0x0d {
			return nil, errors.New("Invalid object name: must not contain CR or LF")
		}
	}

	return newObjectWriter(b, attrs), nil
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) DeleteObject(
	ctx context.Context,
	name string) error {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Do we possess the object with the given name?
	index := b.objects.find(name)
	if index == len(b.objects) {
		return errors.New("Object not found.")
	}

	// Remove the object.
	b.objects = append(b.objects[:index], b.objects[index+1:]...)

	return nil
}

// Create an object struct for the given attributes and contents.
//
// EXCLUSIVE_LOCKS_REQUIRED(b.mu)
func (b *bucket) mintObject(
	attrs *storage.ObjectAttrs,
	contents []byte) (o object) {
	// Set up metadata.
	// TODO(jacobsa): Other fields.
	o.metadata = &storage.Object{
		Bucket:   b.Name(),
		Name:     attrs.Name,
		Owner:    "user-fake",
		Size:     int64(len(contents)),
		Metadata: attrs.Metadata,
	}

	// Set up contents.
	o.contents = contents

	return
}

// Add a record for an object with the given attributes and contents, then
// return the minted metadata.
//
// LOCKS_EXCLUDED(b.mu)
func (b *bucket) addObject(
	attrs *storage.ObjectAttrs,
	contents []byte) *storage.Object {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Create an object record from the given attributes.
	var o object = b.mintObject(attrs, contents)

	// Replace an entry in or add an entry to our list of objects.
	existingIndex := b.objects.find(attrs.Name)
	if existingIndex < len(b.objects) {
		b.objects[existingIndex] = o
	} else {
		b.objects = append(b.objects, o)
		sort.Sort(b.objects)
	}

	return o.metadata
}

func minInt(a, b int) int {
	if a < b {
		return a
	}

	return b
}

func maxInt(a, b int) int {
	if a > b {
		return a
	}

	return b
}
<commit_msg>Fixed a bug: Index, not IndexAny.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsfake

import (
	"errors"
	"fmt"
	"io"
	"sort"
	"strings"
	"unicode/utf8"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

// Create an in-memory bucket with the given name and empty contents.
func NewFakeBucket(name string) gcs.Bucket {
	b := &bucket{name: name}
	b.mu = syncutil.NewInvariantMutex(func() { b.checkInvariants() })
	return b
}

type object struct {
	// A storage.Object representing metadata for this object. Never changes.
	metadata *storage.Object

	// The contents of the object. These never change.
	contents []byte
}

// A slice of objects compared by name.
type objectSlice []object

func (s objectSlice) Len() int           { return len(s) }
func (s objectSlice) Less(i, j int) bool { return s[i].metadata.Name < s[j].metadata.Name }
func (s objectSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

// Return the smallest i such that s[i].metadata.Name >= name, or len(s) if
// there is no such i.
func (s objectSlice) lowerBound(name string) int {
	pred := func(i int) bool {
		return s[i].metadata.Name >= name
	}

	return sort.Search(len(s), pred)
}

// Return the smallest i such that s[i].metadata.Name == name, or len(s) if
// there is no such i.
func (s objectSlice) find(name string) int {
	lb := s.lowerBound(name)
	if lb < len(s) && s[lb].metadata.Name == name {
		return lb
	}

	return len(s)
}

// Return the smallest string that is lexicographically larger than prefix and
// does not have prefix as a prefix. For the sole case where this is not
// possible (all strings consisting solely of 0xff bytes, including the empty
// string), return the empty string.
func prefixSuccessor(prefix string) string {
	// Attempt to increment the last byte. If that is a 0xff byte, erase it and
	// recurse. If we hit an empty string, then we know our task is impossible.
	limit := []byte(prefix)
	for len(limit) > 0 {
		b := limit[len(limit)-1]
		if b != 0xff {
			limit[len(limit)-1]++
			break
		}

		limit = limit[:len(limit)-1]
	}

	return string(limit)
}

// Return the smallest i such that prefix < s[i].metadata.Name and
// !strings.HasPrefix(s[i].metadata.Name, prefix).
func (s objectSlice) prefixUpperBound(prefix string) int {
	successor := prefixSuccessor(prefix)
	if successor == "" {
		return len(s)
	}

	return s.lowerBound(successor)
}

type bucket struct {
	name string
	mu   syncutil.InvariantMutex

	// The set of extant objects.
	//
	// INVARIANT: Strictly increasing.
	objects objectSlice // GUARDED_BY(mu)
}

// SHARED_LOCKS_REQUIRED(b.mu)
func (b *bucket) checkInvariants() {
	// Make sure 'objects' is strictly increasing.
	for i := 1; i < len(b.objects); i++ {
		objA := b.objects[i-1]
		objB := b.objects[i]
		if !(objA.metadata.Name < objB.metadata.Name) {
			panic(
				fmt.Sprintf(
					"Object names are not strictly increasing: %v vs. %v",
					objA.metadata.Name,
					objB.metadata.Name))
		}
	}
}

func (b *bucket) Name() string {
	return b.name
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) ListObjects(
	ctx context.Context,
	query *storage.Query) (listing *storage.Objects, err error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	// Set up the result object.
	listing = new(storage.Objects)

	// Handle nil queries.
	if query == nil {
		query = &storage.Query{}
	}

	// Handle defaults.
	maxResults := query.MaxResults
	if maxResults == 0 {
		maxResults = 1000
	}

	// Find where in the space of object names to start.
	nameStart := query.Prefix
	if query.Cursor != "" && query.Cursor > nameStart {
		nameStart = query.Cursor
	}

	// Find the range of indexes within the array to scan.
	indexStart := b.objects.lowerBound(nameStart)
	prefixLimit := b.objects.prefixUpperBound(query.Prefix)
	indexLimit := minInt(indexStart+maxResults, prefixLimit)

	// Scan the array.
	var lastResultWasPrefix bool
	for i := indexStart; i < indexLimit; i++ {
		var o object = b.objects[i]
		name := o.metadata.Name

		// Search for a delimiter if necessary.
		if query.Delimiter != "" {
			// Search only in the part after the prefix.
			nameMinusQueryPrefix := name[len(query.Prefix):]

			delimiterIndex := strings.Index(nameMinusQueryPrefix, query.Delimiter)
			if delimiterIndex >= 0 {
				resultPrefixLimit := delimiterIndex

				// Transform to an index within name.
				resultPrefixLimit += len(query.Prefix)

				// Include the delimiter in the result.
				resultPrefixLimit += len(query.Delimiter)

				// Save the result, but only if it's not a duplicate.
				resultPrefix := name[:resultPrefixLimit]
				if len(listing.Prefixes) == 0 ||
					listing.Prefixes[len(listing.Prefixes)-1] != resultPrefix {
					listing.Prefixes = append(listing.Prefixes, resultPrefix)
				}

				lastResultWasPrefix = true
				continue
			}
		}

		lastResultWasPrefix = false

		// Otherwise, save as an object result.
		listing.Results = append(listing.Results, o.metadata)
	}

	// Set up a cursor for where to start the next scan if we didn't exhaust the
	// results.
	if indexLimit < prefixLimit {
		listing.Next = &storage.Query{}
		*listing.Next = *query

		// Ion is if the final object we visited was returned as an element in
		// listing.Prefixes, we want to skip all other objects that would result in
		// the same so we don't return duplicate elements in listing.Prefixes
		// accross requests.
		if lastResultWasPrefix {
			lastResultPrefix := listing.Prefixes[len(listing.Prefixes)-1]
			listing.Next.Cursor = prefixSuccessor(lastResultPrefix)

			// Check an assumption: prefixSuccessor cannot result in the empty string
			// above because object names must be non-empty UTF-8 strings, and there
			// is no valid non-empty UTF-8 string that consists of entirely 0xff
			// bytes.
			if listing.Next.Cursor == "" {
				err = errors.New("Unexpected empty string from prefixSuccessor")
				return
			}
		} else {
			// Otherwise, we'll start scanning at the next object.
			listing.Next.Cursor = b.objects[indexLimit].metadata.Name
		}
	}

	return
}

func (b *bucket) NewReader(
	ctx context.Context,
	objectName string) (io.ReadCloser, error) {
	return nil, errors.New("TODO: Implement NewReader.")
}

func (b *bucket) NewWriter(
	ctx context.Context,
	attrs *storage.ObjectAttrs) (gcs.ObjectWriter, error) {
	// Check that the object name is legal.
	name := attrs.Name
	if len(name) == 0 || len(name) > 1024 {
		return nil, errors.New("Invalid object name: length must be in [1, 1024]")
	}

	if !utf8.ValidString(name) {
		return nil, errors.New("Invalid object name: not valid UTF-8")
	}

	for _, r := range name {
		if r == 0x0a || r == 0x0d {
			return nil, errors.New("Invalid object name: must not contain CR or LF")
		}
	}

	return newObjectWriter(b, attrs), nil
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) DeleteObject(
	ctx context.Context,
	name string) error {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Do we possess the object with the given name?
	index := b.objects.find(name)
	if index == len(b.objects) {
		return errors.New("Object not found.")
	}

	// Remove the object.
	b.objects = append(b.objects[:index], b.objects[index+1:]...)

	return nil
}

// Create an object struct for the given attributes and contents.
//
// EXCLUSIVE_LOCKS_REQUIRED(b.mu)
func (b *bucket) mintObject(
	attrs *storage.ObjectAttrs,
	contents []byte) (o object) {
	// Set up metadata.
	// TODO(jacobsa): Other fields.
	o.metadata = &storage.Object{
		Bucket:   b.Name(),
		Name:     attrs.Name,
		Owner:    "user-fake",
		Size:     int64(len(contents)),
		Metadata: attrs.Metadata,
	}

	// Set up contents.
	o.contents = contents

	return
}

// Add a record for an object with the given attributes and contents, then
// return the minted metadata.
//
// LOCKS_EXCLUDED(b.mu)
func (b *bucket) addObject(
	attrs *storage.ObjectAttrs,
	contents []byte) *storage.Object {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Create an object record from the given attributes.
	var o object = b.mintObject(attrs, contents)

	// Replace an entry in or add an entry to our list of objects.
	existingIndex := b.objects.find(attrs.Name)
	if existingIndex < len(b.objects) {
		b.objects[existingIndex] = o
	} else {
		b.objects = append(b.objects, o)
		sort.Sort(b.objects)
	}

	return o.metadata
}

func minInt(a, b int) int {
	if a < b {
		return a
	}

	return b
}

func maxInt(a, b int) int {
	if a > b {
		return a
	}

	return b
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Rook Authors. All rights reserved.

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

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

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

package integration

import (
	"fmt"
	"testing"
	"time"

	"github.com/rook/rook/tests/framework/clients"
	"github.com/rook/rook/tests/framework/installer"
	"github.com/rook/rook/tests/framework/utils"
	"github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
)

// *************************************************************
// *** Major scenarios tested by the MultiClusterDeploySuite ***
// Setup
// - Two clusters started in different namespaces via the CRD
// Monitors
// - One mon in each cluster
// OSDs
// - Bluestore running on a directory
// Block
// - Create a pool in each cluster
// - Mount/unmount a block device through the dynamic provisioner
// File system
// - Create a file system via the CRD
// Object
// - Create the object store via the CRD
// *************************************************************
func TestCephMultiClusterDeploySuite(t *testing.T) {
	if installer.SkipTestSuite(installer.CephTestSuite) {
		t.Skip()
	}

	s := new(MultiClusterDeploySuite)
	defer func(s *MultiClusterDeploySuite) {
		HandlePanics(recover(), s.op, s.T)
	}(s)
	suite.Run(t, s)
}

type MultiClusterDeploySuite struct {
	suite.Suite
	testClient *clients.TestClient
	k8sh       *utils.K8sHelper
	namespace1 string
	namespace2 string
	op         *MCTestOperations
}

// Deploy Multiple Rook clusters
func (mrc *MultiClusterDeploySuite) SetupSuite() {

	mrc.namespace1 = "mrc-n1"
	mrc.namespace2 = "mrc-n2"

	mrc.op, mrc.k8sh = NewMCTestOperations(mrc.T, mrc.namespace1, mrc.namespace2)
	mrc.testClient = clients.CreateTestClient(mrc.k8sh, mrc.op.installer.Manifests)
	mrc.createPools()
}

func (mrc *MultiClusterDeploySuite) AfterTest(suiteName, testName string) {
	mrc.op.installer.CollectOperatorLog(suiteName, testName, mrc.op.systemNamespace)
}

func (mrc *MultiClusterDeploySuite) createPools() {
	// create a test pool in each cluster so that we get some PGs
	poolName := "multi-cluster-pool1"
	logger.Infof("Creating pool %s", poolName)
	err := mrc.testClient.PoolClient.Create(poolName, mrc.namespace1, 1)
	require.Nil(mrc.T(), err)

	poolName = "multi-cluster-pool2"
	logger.Infof("Creating pool %s", poolName)
	err = mrc.testClient.PoolClient.Create(poolName, mrc.namespace2, 1)
	require.Nil(mrc.T(), err)
}

func (mrc *MultiClusterDeploySuite) TearDownSuite() {
	mrc.op.Teardown()
}

// Test to make sure all rook components are installed and Running
func (mrc *MultiClusterDeploySuite) TestInstallingMultipleRookClusters() {
	// Check if Rook cluster 1 is deployed successfully
	checkIfRookClusterIsInstalled(mrc.Suite, mrc.k8sh, installer.SystemNamespace(mrc.namespace1), mrc.namespace1, 1)
	checkIfRookClusterIsHealthy(mrc.Suite, mrc.testClient, mrc.namespace1)

	// Check if Rook cluster 2 is deployed successfully
	checkIfRookClusterIsInstalled(mrc.Suite, mrc.k8sh, installer.SystemNamespace(mrc.namespace1), mrc.namespace2, 1)
	checkIfRookClusterIsHealthy(mrc.Suite, mrc.testClient, mrc.namespace2)
}

// Test Block Store Creation on multiple rook clusters
func (mrc *MultiClusterDeploySuite) TestBlockStoreOnMultipleRookCluster() {
	runBlockE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace1, mrc.op.installer.CephVersion)
	runBlockE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace2, mrc.op.installer.CephVersion)
}

// Test Filesystem Creation on multiple rook clusters
func (mrc *MultiClusterDeploySuite) TestFileStoreOnMultiRookCluster() {
	runFileE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace1, "test-fs-1")
	runFileE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace2, "test-fs-2")
}

// Test Object Store Creation on multiple rook clusters
func (mrc *MultiClusterDeploySuite) TestObjectStoreOnMultiRookCluster() {
	runObjectE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace1, "default-c1", 2)
	runObjectE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace2, "default-c2", 1)
}

// MCTestOperations struct for handling panic and test suite tear down
type MCTestOperations struct {
	installer       *installer.CephInstaller
	kh              *utils.K8sHelper
	T               func() *testing.T
	namespace1      string
	namespace2      string
	systemNamespace string
}

// NewMCTestOperations creates new instance of TestCluster struct
func NewMCTestOperations(t func() *testing.T, namespace1 string, namespace2 string) (*MCTestOperations, *utils.K8sHelper) {

	kh, err := utils.CreateK8sHelper(t)
	require.NoError(t(), err)
	checkIfShouldRunForMinimalTestMatrix(t, kh, multiClusterMinimalTestVersion)

	i := installer.NewCephInstaller(t, kh.Clientset, false, installer.VersionMaster, installer.NautilusVersion)

	op := &MCTestOperations{i, kh, t, namespace1, namespace2, installer.SystemNamespace(namespace1)}
	op.Setup()
	return op, kh
}

// SetUpRook is wrapper for setting up multiple rook clusters.
func (o MCTestOperations) Setup() {
	var err error
	err = o.installer.CreateCephOperator(installer.SystemNamespace(o.namespace1))
	require.NoError(o.T(), err)

	require.True(o.T(), o.kh.IsPodInExpectedState("rook-ceph-operator", o.systemNamespace, "Running"),
		"Make sure rook-operator is in running state")

	require.True(o.T(), o.kh.IsPodInExpectedState("rook-discover", o.systemNamespace, "Running"),
		"Make sure rook-discover is in running state")

	time.Sleep(10 * time.Second)

	// start the two clusters in parallel
	logger.Infof("starting two clusters in parallel")
	errCh1 := make(chan error, 1)
	errCh2 := make(chan error, 1)
	go o.startCluster(o.namespace1, "bluestore", errCh1)
	go o.startCluster(o.namespace2, "filestore", errCh2)
	require.NoError(o.T(), <-errCh1)
	require.NoError(o.T(), <-errCh2)

	require.True(o.T(), o.kh.IsPodInExpectedState("rook-ceph-agent", o.systemNamespace, "Running"),
		"Make sure rook-ceph-agent is in running state")

	logger.Infof("finished starting clusters")
}

// TearDownRook is a wrapper for tearDown after suite
func (o MCTestOperations) Teardown() {
	defer func() {
		if r := recover(); r != nil {
			logger.Infof("Unexpected Errors while cleaning up MultiCluster test --> %v", r)
			o.T().FailNow()
		}
	}()

	o.installer.UninstallRookFromMultipleNS(true, installer.SystemNamespace(o.namespace1), o.namespace1, o.namespace2)
}

func (o MCTestOperations) startCluster(namespace, store string, errCh chan error) {
	logger.Infof("starting cluster %s", namespace)
	if err := o.installer.CreateK8sRookCluster(namespace, o.systemNamespace, store); err != nil {
		o.installer.GatherAllRookLogs(o.T().Name(), namespace, o.systemNamespace)
		errCh <- fmt.Errorf("failed to create cluster %s. %+v", namespace, err)
		return
	}

	if err := o.installer.CreateK8sRookToolbox(namespace); err != nil {
		o.installer.GatherAllRookLogs(o.T().Name(), namespace, o.systemNamespace)
		errCh <- fmt.Errorf("failed to create toolbox for %s. %+v", namespace, err)
		return
	}
	logger.Infof("succeeded starting cluster %s", namespace)
	errCh <- nil
}
<commit_msg>tests: mark failed test for log collection<commit_after>/*
Copyright 2016 The Rook Authors. All rights reserved.

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

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

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

package integration

import (
	"fmt"
	"testing"
	"time"

	"github.com/rook/rook/tests/framework/clients"
	"github.com/rook/rook/tests/framework/installer"
	"github.com/rook/rook/tests/framework/utils"
	"github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
)

// *************************************************************
// *** Major scenarios tested by the MultiClusterDeploySuite ***
// Setup
// - Two clusters started in different namespaces via the CRD
// Monitors
// - One mon in each cluster
// OSDs
// - Bluestore running on a directory
// Block
// - Create a pool in each cluster
// - Mount/unmount a block device through the dynamic provisioner
// File system
// - Create a file system via the CRD
// Object
// - Create the object store via the CRD
// *************************************************************
func TestCephMultiClusterDeploySuite(t *testing.T) {
	if installer.SkipTestSuite(installer.CephTestSuite) {
		t.Skip()
	}

	s := new(MultiClusterDeploySuite)
	defer func(s *MultiClusterDeploySuite) {
		HandlePanics(recover(), s.op, s.T)
	}(s)
	suite.Run(t, s)
}

type MultiClusterDeploySuite struct {
	suite.Suite
	testClient *clients.TestClient
	k8sh       *utils.K8sHelper
	namespace1 string
	namespace2 string
	op         *MCTestOperations
}

// Deploy Multiple Rook clusters
func (mrc *MultiClusterDeploySuite) SetupSuite() {

	mrc.namespace1 = "mrc-n1"
	mrc.namespace2 = "mrc-n2"

	mrc.op, mrc.k8sh = NewMCTestOperations(mrc.T, mrc.namespace1, mrc.namespace2)
	mrc.testClient = clients.CreateTestClient(mrc.k8sh, mrc.op.installer.Manifests)
	mrc.createPools()
}

func (mrc *MultiClusterDeploySuite) AfterTest(suiteName, testName string) {
	mrc.op.installer.CollectOperatorLog(suiteName, testName, mrc.op.systemNamespace)
}

func (mrc *MultiClusterDeploySuite) createPools() {
	// create a test pool in each cluster so that we get some PGs
	poolName := "multi-cluster-pool1"
	logger.Infof("Creating pool %s", poolName)
	err := mrc.testClient.PoolClient.Create(poolName, mrc.namespace1, 1)
	require.Nil(mrc.T(), err)

	poolName = "multi-cluster-pool2"
	logger.Infof("Creating pool %s", poolName)
	err = mrc.testClient.PoolClient.Create(poolName, mrc.namespace2, 1)
	require.Nil(mrc.T(), err)
}

func (mrc *MultiClusterDeploySuite) TearDownSuite() {
	mrc.op.Teardown()
}

// Test to make sure all rook components are installed and Running
func (mrc *MultiClusterDeploySuite) TestInstallingMultipleRookClusters() {
	// Check if Rook cluster 1 is deployed successfully
	checkIfRookClusterIsInstalled(mrc.Suite, mrc.k8sh, installer.SystemNamespace(mrc.namespace1), mrc.namespace1, 1)
	checkIfRookClusterIsHealthy(mrc.Suite, mrc.testClient, mrc.namespace1)

	// Check if Rook cluster 2 is deployed successfully
	checkIfRookClusterIsInstalled(mrc.Suite, mrc.k8sh, installer.SystemNamespace(mrc.namespace1), mrc.namespace2, 1)
	checkIfRookClusterIsHealthy(mrc.Suite, mrc.testClient, mrc.namespace2)
}

// Test Block Store Creation on multiple rook clusters
func (mrc *MultiClusterDeploySuite) TestBlockStoreOnMultipleRookCluster() {
	runBlockE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace1, mrc.op.installer.CephVersion)
	runBlockE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace2, mrc.op.installer.CephVersion)
}

// Test Filesystem Creation on multiple rook clusters
func (mrc *MultiClusterDeploySuite) TestFileStoreOnMultiRookCluster() {
	runFileE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace1, "test-fs-1")
	runFileE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace2, "test-fs-2")
}

// Test Object Store Creation on multiple rook clusters
func (mrc *MultiClusterDeploySuite) TestObjectStoreOnMultiRookCluster() {
	runObjectE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace1, "default-c1", 2)
	runObjectE2ETestLite(mrc.testClient, mrc.k8sh, mrc.Suite, mrc.namespace2, "default-c2", 1)
}

// MCTestOperations struct for handling panic and test suite tear down
type MCTestOperations struct {
	installer       *installer.CephInstaller
	kh              *utils.K8sHelper
	T               func() *testing.T
	namespace1      string
	namespace2      string
	systemNamespace string
}

// NewMCTestOperations creates new instance of TestCluster struct
func NewMCTestOperations(t func() *testing.T, namespace1 string, namespace2 string) (*MCTestOperations, *utils.K8sHelper) {

	kh, err := utils.CreateK8sHelper(t)
	require.NoError(t(), err)
	checkIfShouldRunForMinimalTestMatrix(t, kh, multiClusterMinimalTestVersion)

	i := installer.NewCephInstaller(t, kh.Clientset, false, installer.VersionMaster, installer.NautilusVersion)

	op := &MCTestOperations{i, kh, t, namespace1, namespace2, installer.SystemNamespace(namespace1)}
	op.Setup()
	return op, kh
}

// SetUpRook is wrapper for setting up multiple rook clusters.
func (o MCTestOperations) Setup() {
	var err error
	err = o.installer.CreateCephOperator(installer.SystemNamespace(o.namespace1))
	require.NoError(o.T(), err)

	require.True(o.T(), o.kh.IsPodInExpectedState("rook-ceph-operator", o.systemNamespace, "Running"),
		"Make sure rook-operator is in running state")

	require.True(o.T(), o.kh.IsPodInExpectedState("rook-discover", o.systemNamespace, "Running"),
		"Make sure rook-discover is in running state")

	time.Sleep(10 * time.Second)

	// start the two clusters in parallel
	logger.Infof("starting two clusters in parallel")
	errCh1 := make(chan error, 1)
	errCh2 := make(chan error, 1)
	go o.startCluster(o.namespace1, "bluestore", errCh1)
	go o.startCluster(o.namespace2, "filestore", errCh2)
	require.NoError(o.T(), <-errCh1)
	require.NoError(o.T(), <-errCh2)

	require.True(o.T(), o.kh.IsPodInExpectedState("rook-ceph-agent", o.systemNamespace, "Running"),
		"Make sure rook-ceph-agent is in running state")

	logger.Infof("finished starting clusters")
}

// TearDownRook is a wrapper for tearDown after suite
func (o MCTestOperations) Teardown() {
	defer func() {
		if r := recover(); r != nil {
			logger.Infof("Unexpected Errors while cleaning up MultiCluster test --> %v", r)
			o.T().FailNow()
		}
	}()

	o.installer.UninstallRookFromMultipleNS(true, installer.SystemNamespace(o.namespace1), o.namespace1, o.namespace2)
}

func (o MCTestOperations) startCluster(namespace, store string, errCh chan error) {
	logger.Infof("starting cluster %s", namespace)
	if err := o.installer.CreateK8sRookCluster(namespace, o.systemNamespace, store); err != nil {
		o.T().Fail()
		o.installer.GatherAllRookLogs(o.T().Name(), namespace, o.systemNamespace)
		errCh <- fmt.Errorf("failed to create cluster %s. %+v", namespace, err)
		return
	}

	if err := o.installer.CreateK8sRookToolbox(namespace); err != nil {
		o.T().Fail()
		o.installer.GatherAllRookLogs(o.T().Name(), namespace, o.systemNamespace)
		errCh <- fmt.Errorf("failed to create toolbox for %s. %+v", namespace, err)
		return
	}
	logger.Infof("succeeded starting cluster %s", namespace)
	errCh <- nil
}
<|endoftext|>


<commit_before>package lwip

/*
#cgo CFLAGS: -I./src/include
#include "lwip/tcp.h"
*/
import "C"
import (
	"log"
	"unsafe"
)

//export Output
func Output(p *C.struct_pbuf) C.err_t {
	// In most case, all data are in the same pbuf struct, data copying can be avoid by
	// backing Go slice with C array. Buf if there are multiple pbuf structs holding the
	// data, we must copy data for sending them in one pass.
	if p.tot_len == p.len {
		buf := (*[1 << 30]byte)(unsafe.Pointer(p.payload))[:int(p.len):int(p.len)]
		_, err := OutputFn(buf)
		if err != nil {
			log.Fatal("failed to output packets from stack: %v", err)
		}
	} else {
		buf := NewBytes(int(p.tot_len))
		C.pbuf_copy_partial(p, unsafe.Pointer(&buf[0]), p.tot_len, 0)
		_, err := OutputFn(buf)
		FreeBytes(buf)
		if err != nil {
			log.Fatal("failed to output packets from stack: %v", err)
		}
	}

	return C.ERR_OK
}
<commit_msg>should output tot_len bytes<commit_after>package lwip

/*
#cgo CFLAGS: -I./src/include
#include "lwip/tcp.h"
*/
import "C"
import (
	"log"
	"unsafe"
)

//export Output
func Output(p *C.struct_pbuf) C.err_t {
	// In most case, all data are in the same pbuf struct, data copying can be avoid by
	// backing Go slice with C array. Buf if there are multiple pbuf structs holding the
	// data, we must copy data for sending them in one pass.
	if p.tot_len == p.len {
		buf := (*[1 << 30]byte)(unsafe.Pointer(p.payload))[:int(p.len):int(p.len)]
		_, err := OutputFn(buf)
		if err != nil {
			log.Fatal("failed to output packets from stack: %v", err)
		}
	} else {
		buf := NewBytes(int(p.tot_len))
		C.pbuf_copy_partial(p, unsafe.Pointer(&buf[0]), p.tot_len, 0)
		_, err := OutputFn(buf[:int(p.tot_len)])
		FreeBytes(buf)
		if err != nil {
			log.Fatal("failed to output packets from stack: %v", err)
		}
	}

	return C.ERR_OK
}
<|endoftext|>


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

package markbits

import (
	"errors"
	"sync"

	log "github.com/sirupsen/logrus"
)

// MarkBitsManager provides set of functions to manage an uint32 mark bits based on a given mark mask.
type MarkBitsManager struct {
	name             string
	mask             uint32
	numBitsAllocated int
	numFreeBits      int

	mutex sync.Mutex
}

func NewMarkBitsManager(markMask uint32, markName string) *MarkBitsManager {
	numBitsFound := 0
	for shift := uint(0); shift < 32; shift++ {
		bit := uint32(1) << shift
		if markMask&bit > 0 {
			numBitsFound += 1
		}
	}

	return &MarkBitsManager{
		name:             markName,
		mask:             markMask,
		numBitsAllocated: 0,
		numFreeBits:      numBitsFound,
	}
}

// Allocate next mark bit.
func (mc *MarkBitsManager) NextSigleBitMark() (uint32, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	mark, err := mc.nthMark(mc.numBitsAllocated)
	if err != nil {
		return 0, err
	}
	mc.numFreeBits--
	mc.numBitsAllocated++
	return mark, nil
}

func (mc *MarkBitsManager) AvailableMarkBitCount() int {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()
	return mc.numFreeBits
}

// Allocate a block of bits given a requested size.
// Return allocated mark and how many bits allocated.
func (mc *MarkBitsManager) NextBlockBitsMark(size int) (uint32, int) {
	mark := uint32(0)
	numBitsFound := 0
	numBitsForBlock := 0

	mc.mutex.Lock()
	defer mc.mutex.Unlock()
	for shift := uint(0); shift < 32 && numBitsForBlock < size; shift++ {
		candidate := uint32(1) << shift
		if mc.mask&candidate > 0 {
			numBitsFound++
			if numBitsFound > mc.numBitsAllocated {
				mark |= uint32(candidate)
				numBitsForBlock++
			}
		}
	}

	if numBitsForBlock < size {
		log.WithFields(log.Fields{
			"Name":                   mc.name,
			"MarkMask":               mc.mask,
			"requestedMarkBlockSize": size,
		}).Warning("Not enough mark bits available.")

	}

	// Return as many bits allocated as possible.
	mc.numFreeBits -= numBitsForBlock
	mc.numBitsAllocated += numBitsForBlock
	return mark, numBitsForBlock
}

// Return Nth mark bit without allocation.
func (mc *MarkBitsManager) nthMark(n int) (uint32, error) {
	numBitsFound := 0
	for shift := uint(0); shift < 32; shift++ {
		candidate := uint32(1) << shift
		if mc.mask&candidate > 0 {
			if numBitsFound == n {
				return candidate, nil
			}
			numBitsFound++
		}
	}

	return 0, errors.New("No mark bit found")
}

// Return how many free position number left.
func (mc *MarkBitsManager) CurrentFreeNumberOfMark() int {
	return int(uint32(1) << uint32(mc.numFreeBits))
}

// Return a mark given a position number.
func (mc *MarkBitsManager) MapNumberToMark(n int) uint32 {
	number := uint32(n)
	mark := uint32(0)
	numBitsFound := uint32(0)
	for shift := uint(0); shift < 32 && number > 0; shift++ {
		candidate := uint32(1) << shift
		if mc.mask&candidate > 0 {
			value := number & (uint32(1) << numBitsFound)
			if value > 0 {
				mark |= candidate
				number -= value
			}
			numBitsFound++
		}
	}

	if number > 0 {
		log.WithFields(log.Fields{
			"Name":               mc.name,
			"MarkMask":           mc.mask,
			"requestedMapNumber": n,
		}).Panic("Not enough mark bits available.")
		return 0
	}

	return mark
}

// Return a position number given a mark.
func (mc *MarkBitsManager) MapMarkToNumber(mark uint32) int {
	number := 0
	numBitsFound := uint32(0)
	for shift := uint(0); shift < 32; shift++ {
		bit := uint32(1) << shift
		if mc.mask&bit > 0 {
			if bit&mark > 0 {
				number += int(uint32(1) << numBitsFound)
			}
			numBitsFound++
		}
	}

	return number
}
<commit_msg>UT for Markbits bits allocation.<commit_after>// Copyright (c) 2018 Tigera, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package markbits

import (
	"errors"
	"sync"

	log "github.com/sirupsen/logrus"
)

// MarkBitsManager provides set of functions to manage an uint32 mark bits based on a given mark mask.
type MarkBitsManager struct {
	name             string
	mask             uint32
	numBitsAllocated int
	numFreeBits      int

	mutex sync.Mutex
}

func NewMarkBitsManager(markMask uint32, markName string) *MarkBitsManager {
	numBitsFound := 0
	for shift := uint(0); shift < 32; shift++ {
		bit := uint32(1) << shift
		if markMask&bit > 0 {
			numBitsFound += 1
		}
	}

	return &MarkBitsManager{
		name:             markName,
		mask:             markMask,
		numBitsAllocated: 0,
		numFreeBits:      numBitsFound,
	}
}

// Allocate next mark bit.
func (mc *MarkBitsManager) NextSigleBitMark() (uint32, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	mark, err := mc.nthMark(mc.numBitsAllocated)
	if err != nil {
		return 0, err
	}
	mc.numFreeBits--
	mc.numBitsAllocated++
	return mark, nil
}

func (mc *MarkBitsManager) AvailableMarkBitCount() int {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()
	return mc.numFreeBits
}

// Allocate a block of bits given a requested size.
// Return allocated mark and how many bits allocated.
// It is up to the caller to check the result.
func (mc *MarkBitsManager) NextBlockBitsMark(size int) (uint32, int) {
	mark := uint32(0)
	numBitsFound := 0
	numBitsForBlock := 0

	mc.mutex.Lock()
	defer mc.mutex.Unlock()
	for shift := uint(0); shift < 32 && numBitsForBlock < size; shift++ {
		candidate := uint32(1) << shift
		if mc.mask&candidate > 0 {
			numBitsFound++
			if numBitsFound > mc.numBitsAllocated {
				mark |= uint32(candidate)
				numBitsForBlock++
			}
		}
	}

	if numBitsForBlock < size {
		log.WithFields(log.Fields{
			"Name":                   mc.name,
			"MarkMask":               mc.mask,
			"requestedMarkBlockSize": size,
		}).Warning("Not enough mark bits available.")

	}

	// Return as many bits allocated as possible.
	mc.numFreeBits -= numBitsForBlock
	mc.numBitsAllocated += numBitsForBlock
	return mark, numBitsForBlock
}

// Return Nth mark bit without allocation.
func (mc *MarkBitsManager) nthMark(n int) (uint32, error) {
	numBitsFound := 0
	for shift := uint(0); shift < 32; shift++ {
		candidate := uint32(1) << shift
		if mc.mask&candidate > 0 {
			if numBitsFound == n {
				return candidate, nil
			}
			numBitsFound++
		}
	}

	return 0, errors.New("No mark bit found")
}

// Return how many free position number left.
func (mc *MarkBitsManager) CurrentFreeNumberOfMark() int {
	if mc.numFreeBits > 0 {
		return int(uint64(1) << uint64(mc.numFreeBits))
	}
	return 0
}

// Return a mark given a position number.
func (mc *MarkBitsManager) MapNumberToMark(n int) uint32 {
	number := uint32(n)
	mark := uint32(0)
	numBitsFound := uint32(0)
	for shift := uint(0); shift < 32 && number > 0; shift++ {
		candidate := uint32(1) << shift
		if mc.mask&candidate > 0 {
			value := number & (uint32(1) << numBitsFound)
			if value > 0 {
				mark |= candidate
				number -= value
			}
			numBitsFound++
		}
	}

	if number > 0 {
		log.WithFields(log.Fields{
			"Name":               mc.name,
			"MarkMask":           mc.mask,
			"requestedMapNumber": n,
		}).Panic("Not enough mark bits available.")
		return 0
	}

	return mark
}

// Return a position number given a mark.
func (mc *MarkBitsManager) MapMarkToNumber(mark uint32) int {
	number := 0
	numBitsFound := uint32(0)
	for shift := uint(0); shift < 32; shift++ {
		bit := uint32(1) << shift
		if mc.mask&bit > 0 {
			if bit&mark > 0 {
				number += int(uint32(1) << numBitsFound)
			}
			numBitsFound++
		}
	}

	return number
}
<|endoftext|>


<commit_before>// +build linux

/*
Copyright 2021 The Kubernetes Authors.

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

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

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

package e2enode

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"k8s.io/apimachinery/pkg/fields"

	"github.com/onsi/ginkgo"
	"github.com/onsi/gomega"
	"k8s.io/kubernetes/pkg/apis/scheduling"
	"k8s.io/kubernetes/pkg/features"
	"k8s.io/kubernetes/test/e2e/framework"

	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
	kubelettypes "k8s.io/kubernetes/pkg/kubelet/types"
	testutils "k8s.io/kubernetes/test/utils"
)

var _ = SIGDescribe("GracefulNodeShutdown [Serial] [NodeAlphaFeature:GracefulNodeShutdown]", func() {
	f := framework.NewDefaultFramework("graceful-node-shutdown")
	ginkgo.Context("when gracefully shutting down", func() {

		const (
			pollInterval                        = 1 * time.Second
			podStatusUpdateTimeout              = 5 * time.Second
			nodeStatusUpdateTimeout             = 10 * time.Second
			nodeShutdownGracePeriod             = 20 * time.Second
			nodeShutdownGracePeriodCriticalPods = 10 * time.Second
		)

		tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) {
			initialConfig.FeatureGates = map[string]bool{
				string(features.GracefulNodeShutdown): true,
			}
			initialConfig.ShutdownGracePeriod = metav1.Duration{Duration: nodeShutdownGracePeriod}
			initialConfig.ShutdownGracePeriodCriticalPods = metav1.Duration{Duration: nodeShutdownGracePeriodCriticalPods}
		})

		ginkgo.BeforeEach(func() {
			ginkgo.By("Wait for the node to be ready")
			waitForNodeReady()
		})

		ginkgo.AfterEach(func() {
			ginkgo.By("Emitting Shutdown false signal; cancelling the shutdown")
			err := emitSignalPrepareForShutdown(false)
			framework.ExpectNoError(err)
		})

		ginkgo.It("should be able to gracefully shutdown pods with various grace periods", func() {
			nodeName := getNodeName(f)
			nodeSelector := fields.Set{
				"spec.nodeName": nodeName,
			}.AsSelector().String()

			// Define test pods
			pods := []*v1.Pod{
				getGracePeriodOverrideTestPod("period-120", nodeName, 120, false),
				getGracePeriodOverrideTestPod("period-5", nodeName, 5, false),
				getGracePeriodOverrideTestPod("period-critical-120", nodeName, 120, true),
				getGracePeriodOverrideTestPod("period-critical-5", nodeName, 5, true),
			}

			ginkgo.By("Creating batch pods")
			f.PodClient().CreateBatch(pods)

			list, err := f.PodClient().List(context.TODO(), metav1.ListOptions{
				FieldSelector: nodeSelector,
			})
			framework.ExpectNoError(err)
			framework.ExpectEqual(len(list.Items), len(pods), "the number of pods is not as expected")

			ginkgo.By("Verifying batch pods are running")
			for _, pod := range list.Items {
				if podReady, err := testutils.PodRunningReady(&pod); err != nil || !podReady {
					framework.Failf("Failed to start batch pod: %v", pod.Name)
				}
			}

			ginkgo.By("Emitting shutdown signal")
			err = emitSignalPrepareForShutdown(true)
			framework.ExpectNoError(err)

			ginkgo.By("Verifying that non-critical pods are shutdown")
			// Not critical pod should be shutdown
			gomega.Eventually(func() error {
				list, err = f.PodClient().List(context.TODO(), metav1.ListOptions{
					FieldSelector: nodeSelector,
				})
				if err != nil {
					return err
				}
				framework.ExpectEqual(len(list.Items), len(pods), "the number of pods is not as expected")

				for _, pod := range list.Items {
					if kubelettypes.IsCriticalPod(&pod) {
						if pod.Status.Phase != v1.PodRunning {
							framework.Logf("Expecting critcal pod to be running, but it's not currently. Pod: %q, Pod Status Phase: %q, Pod Status Reason: %q", pod.Name, pod.Status.Phase, pod.Status.Reason)
							return fmt.Errorf("critical pod should not be shutdown, phase: %s", pod.Status.Phase)
						}
					} else {
						if pod.Status.Phase != v1.PodFailed || pod.Status.Reason != "Shutdown" {
							framework.Logf("Expecting non-critcal pod to be shutdown, but it's not currently. Pod: %q, Pod Status Phase: %q, Pod Status Reason: %q", pod.Name, pod.Status.Phase, pod.Status.Reason)
							return fmt.Errorf("pod should be shutdown, phase: %s", pod.Status.Phase)
						}
					}
				}
				return nil
			}, podStatusUpdateTimeout, pollInterval).Should(gomega.BeNil())

			ginkgo.By("Verifying that all pods are shutdown")
			// All pod should be shutdown
			gomega.Eventually(func() error {
				list, err = f.PodClient().List(context.TODO(), metav1.ListOptions{
					FieldSelector: nodeSelector,
				})
				if err != nil {
					return err
				}
				framework.ExpectEqual(len(list.Items), len(pods), "the number of pods is not as expected")

				for _, pod := range list.Items {
					if pod.Status.Phase != v1.PodFailed || pod.Status.Reason != "Shutdown" {
						framework.Logf("Expecting pod to be shutdown, but it's not currently: Pod: %q, Pod Status Phase: %q, Pod Status Reason: %q", pod.Name, pod.Status.Phase, pod.Status.Reason)
						return fmt.Errorf("pod should be shutdown, phase: %s", pod.Status.Phase)
					}
				}
				return nil
			},
				// Critical pod starts shutdown after (nodeShutdownGracePeriod-nodeShutdownGracePeriodCriticalPods)
				podStatusUpdateTimeout+(nodeShutdownGracePeriod-nodeShutdownGracePeriodCriticalPods),
				pollInterval).Should(gomega.BeNil())
		})

		ginkgo.It("should be able to handle a cancelled shutdown", func() {
			ginkgo.By("Emitting Shutdown signal")
			err := emitSignalPrepareForShutdown(true)
			framework.ExpectNoError(err)
			gomega.Eventually(func() error {
				isReady := getNodeReadyStatus(f)
				if isReady {
					return fmt.Errorf("node did not become shutdown as expected")
				}
				return nil
			}, nodeStatusUpdateTimeout, pollInterval).Should(gomega.BeNil())

			ginkgo.By("Emitting Shutdown false signal; cancelling the shutdown")
			err = emitSignalPrepareForShutdown(false)
			framework.ExpectNoError(err)
			gomega.Eventually(func() error {
				isReady := getNodeReadyStatus(f)
				if !isReady {
					return fmt.Errorf("node did not recover as expected")
				}
				return nil
			}, nodeStatusUpdateTimeout, pollInterval).Should(gomega.BeNil())
		})

		ginkgo.It("after restart dbus, should be able to gracefully shutdown", func() {
			// allows manual restart of dbus to work in Ubuntu.
			err := overlayDbusConfig()
			framework.ExpectNoError(err)
			defer func() {
				err := restoreDbusConfig()
				framework.ExpectNoError(err)
			}()

			ginkgo.By("Restart Dbus")
			err = restartDbus()
			framework.ExpectNoError(err)

			ginkgo.By("Emitting Shutdown signal")
			err = emitSignalPrepareForShutdown(true)
			framework.ExpectNoError(err)

			gomega.Eventually(func() error {
				isReady := getNodeReadyStatus(f)
				if isReady {
					return fmt.Errorf("node did not become shutdown as expected")
				}
				return nil
			}, nodeStatusUpdateTimeout, pollInterval).Should(gomega.BeNil())
		})
	})
})

func getGracePeriodOverrideTestPod(name string, node string, gracePeriod int64, critical bool) *v1.Pod {
	pod := &v1.Pod{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Pod",
			APIVersion: "v1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:    name,
					Image:   busyboxImage,
					Command: []string{"sh", "-c"},
					Args: []string{`
_term() {
	echo "Caught SIGTERM signal!"
	while true; do sleep 5; done
}
trap _term SIGTERM
while true; do sleep 5; done
`},
				},
			},
			TerminationGracePeriodSeconds: &gracePeriod,
			NodeName:                      node,
		},
	}
	if critical {
		pod.ObjectMeta.Annotations = map[string]string{
			kubelettypes.ConfigSourceAnnotationKey: kubelettypes.FileSource,
		}
		pod.Spec.PriorityClassName = scheduling.SystemNodeCritical

		framework.ExpectEqual(kubelettypes.IsCriticalPod(pod), true, "pod should be a critical pod")
	} else {
		framework.ExpectEqual(kubelettypes.IsCriticalPod(pod), false, "pod should not be a critical pod")
	}
	return pod
}

// Emits a fake PrepareForShutdown dbus message on system dbus. Will cause kubelet to react to an active shutdown event.
func emitSignalPrepareForShutdown(b bool) error {
	cmd := "dbus-send --system /org/freedesktop/login1 org.freedesktop.login1.Manager.PrepareForShutdown boolean:" + strconv.FormatBool(b)
	_, err := runCommand("sh", "-c", cmd)
	return err
}

func getNodeReadyStatus(f *framework.Framework) bool {
	nodeList, err := f.ClientSet.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
	framework.ExpectNoError(err)
	// Assuming that there is only one node, because this is a node e2e test.
	framework.ExpectEqual(len(nodeList.Items), 1)
	return isNodeReady(&nodeList.Items[0])
}

func restartDbus() error {
	cmd := "systemctl restart dbus"
	_, err := runCommand("sh", "-c", cmd)
	return err
}

func systemctlDaemonReload() error {
	cmd := "systemctl daemon-reload"
	_, err := runCommand("sh", "-c", cmd)
	return err
}

var (
	dbusConfPath = "/etc/systemd/system/dbus.service.d/k8s-graceful-node-shutdown-e2e.conf"
	dbusConf     = `
[Unit]
RefuseManualStart=no
RefuseManualStop=no
[Service]
KillMode=control-group
ExecStop=
`
)

func overlayDbusConfig() error {
	err := os.MkdirAll(filepath.Dir(dbusConf), 0755)
	if err != nil {
		return err
	}
	err = os.WriteFile(dbusConfPath, []byte(dbusConf), 0644)
	if err != nil {
		return err
	}
	return systemctlDaemonReload()
}

func restoreDbusConfig() error {
	err := os.Remove(dbusConf)
	if err != nil {
		return err
	}
	return systemctlDaemonReload()
}
<commit_msg>Fix dbus config path for GracefulNodeShutdown e2e<commit_after>// +build linux

/*
Copyright 2021 The Kubernetes Authors.

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

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

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

package e2enode

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"k8s.io/apimachinery/pkg/fields"

	"github.com/onsi/ginkgo"
	"github.com/onsi/gomega"
	"k8s.io/kubernetes/pkg/apis/scheduling"
	"k8s.io/kubernetes/pkg/features"
	"k8s.io/kubernetes/test/e2e/framework"

	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
	kubelettypes "k8s.io/kubernetes/pkg/kubelet/types"
	testutils "k8s.io/kubernetes/test/utils"
)

var _ = SIGDescribe("GracefulNodeShutdown [Serial] [NodeAlphaFeature:GracefulNodeShutdown]", func() {
	f := framework.NewDefaultFramework("graceful-node-shutdown")
	ginkgo.Context("when gracefully shutting down", func() {

		const (
			pollInterval                        = 1 * time.Second
			podStatusUpdateTimeout              = 5 * time.Second
			nodeStatusUpdateTimeout             = 10 * time.Second
			nodeShutdownGracePeriod             = 20 * time.Second
			nodeShutdownGracePeriodCriticalPods = 10 * time.Second
		)

		tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) {
			initialConfig.FeatureGates = map[string]bool{
				string(features.GracefulNodeShutdown): true,
			}
			initialConfig.ShutdownGracePeriod = metav1.Duration{Duration: nodeShutdownGracePeriod}
			initialConfig.ShutdownGracePeriodCriticalPods = metav1.Duration{Duration: nodeShutdownGracePeriodCriticalPods}
		})

		ginkgo.BeforeEach(func() {
			ginkgo.By("Wait for the node to be ready")
			waitForNodeReady()
		})

		ginkgo.AfterEach(func() {
			ginkgo.By("Emitting Shutdown false signal; cancelling the shutdown")
			err := emitSignalPrepareForShutdown(false)
			framework.ExpectNoError(err)
		})

		ginkgo.It("should be able to gracefully shutdown pods with various grace periods", func() {
			nodeName := getNodeName(f)
			nodeSelector := fields.Set{
				"spec.nodeName": nodeName,
			}.AsSelector().String()

			// Define test pods
			pods := []*v1.Pod{
				getGracePeriodOverrideTestPod("period-120", nodeName, 120, false),
				getGracePeriodOverrideTestPod("period-5", nodeName, 5, false),
				getGracePeriodOverrideTestPod("period-critical-120", nodeName, 120, true),
				getGracePeriodOverrideTestPod("period-critical-5", nodeName, 5, true),
			}

			ginkgo.By("Creating batch pods")
			f.PodClient().CreateBatch(pods)

			list, err := f.PodClient().List(context.TODO(), metav1.ListOptions{
				FieldSelector: nodeSelector,
			})
			framework.ExpectNoError(err)
			framework.ExpectEqual(len(list.Items), len(pods), "the number of pods is not as expected")

			ginkgo.By("Verifying batch pods are running")
			for _, pod := range list.Items {
				if podReady, err := testutils.PodRunningReady(&pod); err != nil || !podReady {
					framework.Failf("Failed to start batch pod: %v", pod.Name)
				}
			}

			ginkgo.By("Emitting shutdown signal")
			err = emitSignalPrepareForShutdown(true)
			framework.ExpectNoError(err)

			ginkgo.By("Verifying that non-critical pods are shutdown")
			// Not critical pod should be shutdown
			gomega.Eventually(func() error {
				list, err = f.PodClient().List(context.TODO(), metav1.ListOptions{
					FieldSelector: nodeSelector,
				})
				if err != nil {
					return err
				}
				framework.ExpectEqual(len(list.Items), len(pods), "the number of pods is not as expected")

				for _, pod := range list.Items {
					if kubelettypes.IsCriticalPod(&pod) {
						if pod.Status.Phase != v1.PodRunning {
							framework.Logf("Expecting critcal pod to be running, but it's not currently. Pod: %q, Pod Status Phase: %q, Pod Status Reason: %q", pod.Name, pod.Status.Phase, pod.Status.Reason)
							return fmt.Errorf("critical pod should not be shutdown, phase: %s", pod.Status.Phase)
						}
					} else {
						if pod.Status.Phase != v1.PodFailed || pod.Status.Reason != "Shutdown" {
							framework.Logf("Expecting non-critcal pod to be shutdown, but it's not currently. Pod: %q, Pod Status Phase: %q, Pod Status Reason: %q", pod.Name, pod.Status.Phase, pod.Status.Reason)
							return fmt.Errorf("pod should be shutdown, phase: %s", pod.Status.Phase)
						}
					}
				}
				return nil
			}, podStatusUpdateTimeout, pollInterval).Should(gomega.BeNil())

			ginkgo.By("Verifying that all pods are shutdown")
			// All pod should be shutdown
			gomega.Eventually(func() error {
				list, err = f.PodClient().List(context.TODO(), metav1.ListOptions{
					FieldSelector: nodeSelector,
				})
				if err != nil {
					return err
				}
				framework.ExpectEqual(len(list.Items), len(pods), "the number of pods is not as expected")

				for _, pod := range list.Items {
					if pod.Status.Phase != v1.PodFailed || pod.Status.Reason != "Shutdown" {
						framework.Logf("Expecting pod to be shutdown, but it's not currently: Pod: %q, Pod Status Phase: %q, Pod Status Reason: %q", pod.Name, pod.Status.Phase, pod.Status.Reason)
						return fmt.Errorf("pod should be shutdown, phase: %s", pod.Status.Phase)
					}
				}
				return nil
			},
				// Critical pod starts shutdown after (nodeShutdownGracePeriod-nodeShutdownGracePeriodCriticalPods)
				podStatusUpdateTimeout+(nodeShutdownGracePeriod-nodeShutdownGracePeriodCriticalPods),
				pollInterval).Should(gomega.BeNil())
		})

		ginkgo.It("should be able to handle a cancelled shutdown", func() {
			ginkgo.By("Emitting Shutdown signal")
			err := emitSignalPrepareForShutdown(true)
			framework.ExpectNoError(err)
			gomega.Eventually(func() error {
				isReady := getNodeReadyStatus(f)
				if isReady {
					return fmt.Errorf("node did not become shutdown as expected")
				}
				return nil
			}, nodeStatusUpdateTimeout, pollInterval).Should(gomega.BeNil())

			ginkgo.By("Emitting Shutdown false signal; cancelling the shutdown")
			err = emitSignalPrepareForShutdown(false)
			framework.ExpectNoError(err)
			gomega.Eventually(func() error {
				isReady := getNodeReadyStatus(f)
				if !isReady {
					return fmt.Errorf("node did not recover as expected")
				}
				return nil
			}, nodeStatusUpdateTimeout, pollInterval).Should(gomega.BeNil())
		})

		ginkgo.It("after restart dbus, should be able to gracefully shutdown", func() {
			// allows manual restart of dbus to work in Ubuntu.
			err := overlayDbusConfig()
			framework.ExpectNoError(err)
			defer func() {
				err := restoreDbusConfig()
				framework.ExpectNoError(err)
			}()

			ginkgo.By("Restart Dbus")
			err = restartDbus()
			framework.ExpectNoError(err)

			ginkgo.By("Emitting Shutdown signal")
			err = emitSignalPrepareForShutdown(true)
			framework.ExpectNoError(err)

			gomega.Eventually(func() error {
				isReady := getNodeReadyStatus(f)
				if isReady {
					return fmt.Errorf("node did not become shutdown as expected")
				}
				return nil
			}, nodeStatusUpdateTimeout, pollInterval).Should(gomega.BeNil())
		})
	})
})

func getGracePeriodOverrideTestPod(name string, node string, gracePeriod int64, critical bool) *v1.Pod {
	pod := &v1.Pod{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Pod",
			APIVersion: "v1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:    name,
					Image:   busyboxImage,
					Command: []string{"sh", "-c"},
					Args: []string{`
_term() {
	echo "Caught SIGTERM signal!"
	while true; do sleep 5; done
}
trap _term SIGTERM
while true; do sleep 5; done
`},
				},
			},
			TerminationGracePeriodSeconds: &gracePeriod,
			NodeName:                      node,
		},
	}
	if critical {
		pod.ObjectMeta.Annotations = map[string]string{
			kubelettypes.ConfigSourceAnnotationKey: kubelettypes.FileSource,
		}
		pod.Spec.PriorityClassName = scheduling.SystemNodeCritical

		framework.ExpectEqual(kubelettypes.IsCriticalPod(pod), true, "pod should be a critical pod")
	} else {
		framework.ExpectEqual(kubelettypes.IsCriticalPod(pod), false, "pod should not be a critical pod")
	}
	return pod
}

// Emits a fake PrepareForShutdown dbus message on system dbus. Will cause kubelet to react to an active shutdown event.
func emitSignalPrepareForShutdown(b bool) error {
	cmd := "dbus-send --system /org/freedesktop/login1 org.freedesktop.login1.Manager.PrepareForShutdown boolean:" + strconv.FormatBool(b)
	_, err := runCommand("sh", "-c", cmd)
	return err
}

func getNodeReadyStatus(f *framework.Framework) bool {
	nodeList, err := f.ClientSet.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
	framework.ExpectNoError(err)
	// Assuming that there is only one node, because this is a node e2e test.
	framework.ExpectEqual(len(nodeList.Items), 1)
	return isNodeReady(&nodeList.Items[0])
}

func restartDbus() error {
	cmd := "systemctl restart dbus"
	_, err := runCommand("sh", "-c", cmd)
	return err
}

func systemctlDaemonReload() error {
	cmd := "systemctl daemon-reload"
	_, err := runCommand("sh", "-c", cmd)
	return err
}

var (
	dbusConfPath = "/etc/systemd/system/dbus.service.d/k8s-graceful-node-shutdown-e2e.conf"
	dbusConf     = `
[Unit]
RefuseManualStart=no
RefuseManualStop=no
[Service]
KillMode=control-group
ExecStop=
`
)

func overlayDbusConfig() error {
	err := os.MkdirAll(filepath.Dir(dbusConfPath), 0755)
	if err != nil {
		return err
	}
	err = os.WriteFile(dbusConfPath, []byte(dbusConf), 0644)
	if err != nil {
		return err
	}
	return systemctlDaemonReload()
}

func restoreDbusConfig() error {
	err := os.Remove(dbusConfPath)
	if err != nil {
		return err
	}
	return systemctlDaemonReload()
}
<|endoftext|>


<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct

import (
	"encoding/json"
	"fmt"

	jsonpatch "github.com/evanphx/json-patch"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/strategicpatch"
	"k8s.io/client-go/kubernetes/scheme"
	"sigs.k8s.io/kustomize/api/ifc"
	"sigs.k8s.io/kustomize/api/resid"
)

var _ ifc.Kunstructured = &UnstructAdapter{}

// UnstructAdapter wraps unstructured.Unstructured from
// https://github.com/kubernetes/apimachinery/blob/master/
//     pkg/apis/meta/v1/unstructured/unstructured.go
// to isolate dependence on apimachinery.
type UnstructAdapter struct {
	unstructured.Unstructured
}

// NewKunstructuredFromObject returns a new instance of Kunstructured.
func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) {
	// Convert obj to a byte stream, then convert that to JSON (Unstructured).
	marshaled, err := json.Marshal(obj)
	if err != nil {
		return &UnstructAdapter{}, err
	}
	var u unstructured.Unstructured
	err = u.UnmarshalJSON(marshaled)
	// creationTimestamp always 'null', remove it
	u.SetCreationTimestamp(metav1.Time{})
	return &UnstructAdapter{Unstructured: u}, err
}

// GetGvk returns the Gvk name of the object.
func (fs *UnstructAdapter) GetGvk() resid.Gvk {
	x := fs.GroupVersionKind()
	return resid.Gvk{
		Group:   x.Group,
		Version: x.Version,
		Kind:    x.Kind,
	}
}

// SetGvk set the Gvk of the object to the input Gvk
func (fs *UnstructAdapter) SetGvk(g resid.Gvk) {
	fs.SetGroupVersionKind(toSchemaGvk(g))
}

// Copy provides a copy behind an interface.
func (fs *UnstructAdapter) Copy() ifc.Kunstructured {
	return &UnstructAdapter{*fs.DeepCopy()}
}

// Map returns the unstructured content map.
func (fs *UnstructAdapter) Map() map[string]interface{} {
	return fs.Object
}

// SetMap overrides the unstructured content map.
func (fs *UnstructAdapter) SetMap(m map[string]interface{}) {
	fs.Object = m
}

func (fs *UnstructAdapter) selectSubtree(path string) (map[string]interface{}, []string, bool, error) {
	sections, err := parseFields(path)
	if len(sections) == 0 || (err != nil) {
		return nil, nil, false, err
	}

	content := fs.UnstructuredContent()
	lastSectionIdx := len(sections)

	// There are multiple sections to walk
	for sectionIdx := 0; sectionIdx < lastSectionIdx; sectionIdx++ {
		idx := sections[sectionIdx].idx
		fields := sections[sectionIdx].fields

		if idx == -1 {
			// This section has no index
			return content, fields, true, nil
		}

		// This section is terminated by an indexed field.
		// Let's extract the slice first
		indexedField, found, err := unstructured.NestedFieldNoCopy(content, fields...)
		if !found || err != nil {
			return content, fields, found, err
		}
		s, ok := indexedField.([]interface{})
		if !ok {
			return content, fields, false, fmt.Errorf("%v is of the type %T, expected []interface{}", indexedField, indexedField)
		}
		if idx >= len(s) {
			return content, fields, false, fmt.Errorf("index %d is out of bounds", idx)
		}

		if sectionIdx == lastSectionIdx-1 {
			// This is the last section. Let's build a fake map
			// to let the rest of the field extraction to work.
			idxstring := fmt.Sprintf("[%v]", idx)
			newContent := map[string]interface{}{idxstring: s[idx]}
			newFields := []string{idxstring}
			return newContent, newFields, true, nil
		}

		newContent, ok := s[idx].(map[string]interface{})
		if !ok {
			// Only map are supported here
			return content, fields, false,
				fmt.Errorf("%#v is expected to be of type map[string]interface{}", s[idx])
		}
		content = newContent
	}

	// It seems to be an invalid path
	return nil, []string{}, false, nil
}

// GetFieldValue returns the value at the given fieldpath.
func (fs *UnstructAdapter) GetFieldValue(path string) (interface{}, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return nil, noFieldError{Field: path}
	}

	s, found, err := unstructured.NestedFieldNoCopy(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return nil, noFieldError{Field: path}
}

// GetString returns value at the given fieldpath.
func (fs *UnstructAdapter) GetString(path string) (string, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return "", noFieldError{Field: path}
	}

	s, found, err := unstructured.NestedString(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return "", noFieldError{Field: path}
}

// GetStringSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringSlice(path string) ([]string, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return []string{}, noFieldError{Field: path}
	}

	s, found, err := unstructured.NestedStringSlice(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return []string{}, noFieldError{Field: path}
}

// GetBool returns value at the given fieldpath.
func (fs *UnstructAdapter) GetBool(path string) (bool, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return false, noFieldError{Field: path}
	}

	s, found, err := unstructured.NestedBool(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return false, noFieldError{Field: path}
}

// GetFloat64 returns value at the given fieldpath.
func (fs *UnstructAdapter) GetFloat64(path string) (float64, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return 0, err
	}

	s, found, err := unstructured.NestedFloat64(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return 0, noFieldError{Field: path}
}

// GetInt64 returns value at the given fieldpath.
func (fs *UnstructAdapter) GetInt64(path string) (int64, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return 0, noFieldError{Field: path}
	}

	s, found, err := unstructured.NestedInt64(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return 0, noFieldError{Field: path}
}

// GetSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetSlice(path string) ([]interface{}, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return nil, noFieldError{Field: path}
	}

	s, found, err := unstructured.NestedSlice(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return nil, noFieldError{Field: path}
}

// GetStringMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringMap(path string) (map[string]string, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return nil, noFieldError{Field: path}
	}

	s, found, err := unstructured.NestedStringMap(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return nil, noFieldError{Field: path}
}

// GetMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetMap(path string) (map[string]interface{}, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return nil, noFieldError{Field: path}
	}

	s, found, err := unstructured.NestedMap(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return nil, noFieldError{Field: path}
}

func (fs *UnstructAdapter) MatchesLabelSelector(selector string) (bool, error) {
	s, err := labels.Parse(selector)
	if err != nil {
		return false, err
	}
	return s.Matches(labels.Set(fs.GetLabels())), nil
}

func (fs *UnstructAdapter) MatchesAnnotationSelector(selector string) (bool, error) {
	s, err := labels.Parse(selector)
	if err != nil {
		return false, err
	}
	return s.Matches(labels.Set(fs.GetAnnotations())), nil
}

func (fs *UnstructAdapter) Patch(patch ifc.Kunstructured) error {
	versionedObj, err := scheme.Scheme.New(
		toSchemaGvk(patch.GetGvk()))
	merged := map[string]interface{}{}
	saveName := fs.GetName()
	switch {
	case runtime.IsNotRegisteredError(err):
		baseBytes, err := json.Marshal(fs.Map())
		if err != nil {
			return err
		}
		patchBytes, err := json.Marshal(patch.Map())
		if err != nil {
			return err
		}
		mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes)
		if err != nil {
			return err
		}
		err = json.Unmarshal(mergedBytes, &merged)
		if err != nil {
			return err
		}
	case err != nil:
		return err
	default:
		// Use Strategic-Merge-Patch to handle types w/ schema
		// TODO: Change this to use the new Merge package.
		// Store the name of the target object, because this name may have been munged.
		// Apply this name to the patched object.
		lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
		if err != nil {
			return err
		}
		merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(
			fs.Map(),
			patch.Map(),
			lookupPatchMeta)
		if err != nil {
			return err
		}
	}
	fs.SetMap(merged)
	if len(fs.Map()) != 0 {
		// if the patch deletes the object
		// don't reset the name
		fs.SetName(saveName)
	}
	return nil
}

// toSchemaGvk converts to a schema.GroupVersionKind.
func toSchemaGvk(x resid.Gvk) schema.GroupVersionKind {
	return schema.GroupVersionKind{
		Group:   x.Group,
		Version: x.Version,
		Kind:    x.Kind,
	}
}

// noFieldError is returned when a field is expected, but missing.
type noFieldError struct {
	Field string
}

func (e noFieldError) Error() string {
	return fmt.Sprintf("no field named '%s'", e.Field)
}
<commit_msg>Export noFieldError<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct

import (
	"encoding/json"
	"fmt"

	jsonpatch "github.com/evanphx/json-patch"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/strategicpatch"
	"k8s.io/client-go/kubernetes/scheme"
	"sigs.k8s.io/kustomize/api/ifc"
	"sigs.k8s.io/kustomize/api/resid"
)

var _ ifc.Kunstructured = &UnstructAdapter{}

// UnstructAdapter wraps unstructured.Unstructured from
// https://github.com/kubernetes/apimachinery/blob/master/
//     pkg/apis/meta/v1/unstructured/unstructured.go
// to isolate dependence on apimachinery.
type UnstructAdapter struct {
	unstructured.Unstructured
}

// NewKunstructuredFromObject returns a new instance of Kunstructured.
func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) {
	// Convert obj to a byte stream, then convert that to JSON (Unstructured).
	marshaled, err := json.Marshal(obj)
	if err != nil {
		return &UnstructAdapter{}, err
	}
	var u unstructured.Unstructured
	err = u.UnmarshalJSON(marshaled)
	// creationTimestamp always 'null', remove it
	u.SetCreationTimestamp(metav1.Time{})
	return &UnstructAdapter{Unstructured: u}, err
}

// GetGvk returns the Gvk name of the object.
func (fs *UnstructAdapter) GetGvk() resid.Gvk {
	x := fs.GroupVersionKind()
	return resid.Gvk{
		Group:   x.Group,
		Version: x.Version,
		Kind:    x.Kind,
	}
}

// SetGvk set the Gvk of the object to the input Gvk
func (fs *UnstructAdapter) SetGvk(g resid.Gvk) {
	fs.SetGroupVersionKind(toSchemaGvk(g))
}

// Copy provides a copy behind an interface.
func (fs *UnstructAdapter) Copy() ifc.Kunstructured {
	return &UnstructAdapter{*fs.DeepCopy()}
}

// Map returns the unstructured content map.
func (fs *UnstructAdapter) Map() map[string]interface{} {
	return fs.Object
}

// SetMap overrides the unstructured content map.
func (fs *UnstructAdapter) SetMap(m map[string]interface{}) {
	fs.Object = m
}

func (fs *UnstructAdapter) selectSubtree(path string) (map[string]interface{}, []string, bool, error) {
	sections, err := parseFields(path)
	if len(sections) == 0 || (err != nil) {
		return nil, nil, false, err
	}

	content := fs.UnstructuredContent()
	lastSectionIdx := len(sections)

	// There are multiple sections to walk
	for sectionIdx := 0; sectionIdx < lastSectionIdx; sectionIdx++ {
		idx := sections[sectionIdx].idx
		fields := sections[sectionIdx].fields

		if idx == -1 {
			// This section has no index
			return content, fields, true, nil
		}

		// This section is terminated by an indexed field.
		// Let's extract the slice first
		indexedField, found, err := unstructured.NestedFieldNoCopy(content, fields...)
		if !found || err != nil {
			return content, fields, found, err
		}
		s, ok := indexedField.([]interface{})
		if !ok {
			return content, fields, false, fmt.Errorf("%v is of the type %T, expected []interface{}", indexedField, indexedField)
		}
		if idx >= len(s) {
			return content, fields, false, fmt.Errorf("index %d is out of bounds", idx)
		}

		if sectionIdx == lastSectionIdx-1 {
			// This is the last section. Let's build a fake map
			// to let the rest of the field extraction to work.
			idxstring := fmt.Sprintf("[%v]", idx)
			newContent := map[string]interface{}{idxstring: s[idx]}
			newFields := []string{idxstring}
			return newContent, newFields, true, nil
		}

		newContent, ok := s[idx].(map[string]interface{})
		if !ok {
			// Only map are supported here
			return content, fields, false,
				fmt.Errorf("%#v is expected to be of type map[string]interface{}", s[idx])
		}
		content = newContent
	}

	// It seems to be an invalid path
	return nil, []string{}, false, nil
}

// GetFieldValue returns the value at the given fieldpath.
func (fs *UnstructAdapter) GetFieldValue(path string) (interface{}, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return nil, NoFieldError{Field: path}
	}

	s, found, err := unstructured.NestedFieldNoCopy(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return nil, NoFieldError{Field: path}
}

// GetString returns value at the given fieldpath.
func (fs *UnstructAdapter) GetString(path string) (string, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return "", NoFieldError{Field: path}
	}

	s, found, err := unstructured.NestedString(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return "", NoFieldError{Field: path}
}

// GetStringSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringSlice(path string) ([]string, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return []string{}, NoFieldError{Field: path}
	}

	s, found, err := unstructured.NestedStringSlice(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return []string{}, NoFieldError{Field: path}
}

// GetBool returns value at the given fieldpath.
func (fs *UnstructAdapter) GetBool(path string) (bool, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return false, NoFieldError{Field: path}
	}

	s, found, err := unstructured.NestedBool(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return false, NoFieldError{Field: path}
}

// GetFloat64 returns value at the given fieldpath.
func (fs *UnstructAdapter) GetFloat64(path string) (float64, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return 0, err
	}

	s, found, err := unstructured.NestedFloat64(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return 0, NoFieldError{Field: path}
}

// GetInt64 returns value at the given fieldpath.
func (fs *UnstructAdapter) GetInt64(path string) (int64, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return 0, NoFieldError{Field: path}
	}

	s, found, err := unstructured.NestedInt64(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return 0, NoFieldError{Field: path}
}

// GetSlice returns value at the given fieldpath.
func (fs *UnstructAdapter) GetSlice(path string) ([]interface{}, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return nil, NoFieldError{Field: path}
	}

	s, found, err := unstructured.NestedSlice(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return nil, NoFieldError{Field: path}
}

// GetStringMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetStringMap(path string) (map[string]string, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return nil, NoFieldError{Field: path}
	}

	s, found, err := unstructured.NestedStringMap(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return nil, NoFieldError{Field: path}
}

// GetMap returns value at the given fieldpath.
func (fs *UnstructAdapter) GetMap(path string) (map[string]interface{}, error) {
	content, fields, found, err := fs.selectSubtree(path)
	if !found || err != nil {
		return nil, NoFieldError{Field: path}
	}

	s, found, err := unstructured.NestedMap(
		content, fields...)
	if found || err != nil {
		return s, err
	}
	return nil, NoFieldError{Field: path}
}

func (fs *UnstructAdapter) MatchesLabelSelector(selector string) (bool, error) {
	s, err := labels.Parse(selector)
	if err != nil {
		return false, err
	}
	return s.Matches(labels.Set(fs.GetLabels())), nil
}

func (fs *UnstructAdapter) MatchesAnnotationSelector(selector string) (bool, error) {
	s, err := labels.Parse(selector)
	if err != nil {
		return false, err
	}
	return s.Matches(labels.Set(fs.GetAnnotations())), nil
}

func (fs *UnstructAdapter) Patch(patch ifc.Kunstructured) error {
	versionedObj, err := scheme.Scheme.New(
		toSchemaGvk(patch.GetGvk()))
	merged := map[string]interface{}{}
	saveName := fs.GetName()
	switch {
	case runtime.IsNotRegisteredError(err):
		baseBytes, err := json.Marshal(fs.Map())
		if err != nil {
			return err
		}
		patchBytes, err := json.Marshal(patch.Map())
		if err != nil {
			return err
		}
		mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes)
		if err != nil {
			return err
		}
		err = json.Unmarshal(mergedBytes, &merged)
		if err != nil {
			return err
		}
	case err != nil:
		return err
	default:
		// Use Strategic-Merge-Patch to handle types w/ schema
		// TODO: Change this to use the new Merge package.
		// Store the name of the target object, because this name may have been munged.
		// Apply this name to the patched object.
		lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
		if err != nil {
			return err
		}
		merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(
			fs.Map(),
			patch.Map(),
			lookupPatchMeta)
		if err != nil {
			return err
		}
	}
	fs.SetMap(merged)
	if len(fs.Map()) != 0 {
		// if the patch deletes the object
		// don't reset the name
		fs.SetName(saveName)
	}
	return nil
}

// toSchemaGvk converts to a schema.GroupVersionKind.
func toSchemaGvk(x resid.Gvk) schema.GroupVersionKind {
	return schema.GroupVersionKind{
		Group:   x.Group,
		Version: x.Version,
		Kind:    x.Kind,
	}
}

// NoFieldError is returned when a field is expected, but missing.
type NoFieldError struct {
	Field string
}

func (e NoFieldError) Error() string {
	return fmt.Sprintf("no field named '%s'", e.Field)
}
<|endoftext|>


<commit_before>package chart

import (
	"fmt"
	"time"

	"github.com/wcharczuk/go-chart/date"
)

// MarketHoursRange is a special type of range that compresses a time range into just the
// market (i.e. NYSE operating hours and days) range.
type MarketHoursRange struct {
	Min time.Time
	Max time.Time

	MarketOpen  time.Time
	MarketClose time.Time

	HolidayProvider date.HolidayProvider

	Domain int
}

// IsZero returns if the range is setup or not.
func (mhr MarketHoursRange) IsZero() bool {
	return mhr.Min.IsZero() && mhr.Max.IsZero()
}

// GetMin returns the min value.
func (mhr MarketHoursRange) GetMin() float64 {
	return TimeToFloat64(mhr.Min)
}

// GetMax returns the max value.
func (mhr MarketHoursRange) GetMax() float64 {
	return TimeToFloat64(mhr.Max)
}

// SetMin sets the min value.
func (mhr *MarketHoursRange) SetMin(min float64) {
	mhr.Min = Float64ToTime(min)
}

// SetMax sets the max value.
func (mhr *MarketHoursRange) SetMax(max float64) {
	mhr.Max = Float64ToTime(max)
}

// GetDelta gets the delta.
func (mhr MarketHoursRange) GetDelta() float64 {
	min := TimeToFloat64(mhr.Min)
	max := TimeToFloat64(mhr.Max)
	return max - min
}

// GetDomain gets the domain.
func (mhr MarketHoursRange) GetDomain() int {
	return mhr.Domain
}

// SetDomain sets the domain.
func (mhr *MarketHoursRange) SetDomain(domain int) {
	mhr.Domain = domain
}

// GetHolidayProvider coalesces a userprovided holiday provider and the date.DefaultHolidayProvider.
func (mhr MarketHoursRange) GetHolidayProvider() date.HolidayProvider {
	if mhr.HolidayProvider == nil {
		return date.DefaultHolidayProvider
	}
	return mhr.HolidayProvider
}

// GetTicks returns the ticks for the range.
// This is to override the default continous ticks that would be generated for the range.
func (mhr *MarketHoursRange) GetTicks(vf ValueFormatter) []Tick {
	// return one tick per day
	// figure out how to advance one ticke per market day.
	var ticks []Tick

	cursor := date.On(mhr.MarketClose, mhr.Min)
	maxClose := date.On(mhr.MarketClose, mhr.Max)
	for date.BeforeDate(cursor, maxClose) {
		if date.IsWeekDay(cursor.Weekday()) && !mhr.GetHolidayProvider()(cursor) {
			ticks = append(ticks, Tick{
				Value: TimeToFloat64(cursor),
				Label: vf(cursor),
			})
		}

		cursor = cursor.AddDate(0, 0, 1)
	}

	endMarketClose := date.On(mhr.MarketClose, cursor)
	if date.IsWeekDay(endMarketClose.Weekday()) && !mhr.GetHolidayProvider()(endMarketClose) {
		ticks = append(ticks, Tick{
			Value: TimeToFloat64(endMarketClose),
			Label: vf(endMarketClose),
		})
	}
	return ticks
}

func (mhr MarketHoursRange) String() string {
	return fmt.Sprintf("MarketHoursRange [%s, %s] => %d", mhr.Min.Format(DefaultDateFormat), mhr.Max.Format(DefaultDateFormat), mhr.Domain)
}

// Translate maps a given value into the ContinuousRange space.
func (mhr MarketHoursRange) Translate(value float64) int {
	valueTime := Float64ToTime(value)
	valueTimeEastern := valueTime.In(date.Eastern())
	deltaSeconds := date.CalculateMarketSecondsBetween(mhr.Min, mhr.Max, mhr.MarketOpen, mhr.MarketClose, mhr.HolidayProvider)
	valueDelta := date.CalculateMarketSecondsBetween(mhr.Min, valueTimeEastern, mhr.MarketOpen, mhr.MarketClose, mhr.HolidayProvider)
	translated := int((float64(valueDelta) / float64(deltaSeconds)) * float64(mhr.Domain))
	return translated
}
<commit_msg>switching the formatter<commit_after>package chart

import (
	"fmt"
	"time"

	"github.com/wcharczuk/go-chart/date"
)

// MarketHoursRange is a special type of range that compresses a time range into just the
// market (i.e. NYSE operating hours and days) range.
type MarketHoursRange struct {
	Min time.Time
	Max time.Time

	MarketOpen  time.Time
	MarketClose time.Time

	HolidayProvider date.HolidayProvider

	ValueFormatter ValueFormatter

	Domain int
}

// IsZero returns if the range is setup or not.
func (mhr MarketHoursRange) IsZero() bool {
	return mhr.Min.IsZero() && mhr.Max.IsZero()
}

// GetMin returns the min value.
func (mhr MarketHoursRange) GetMin() float64 {
	return TimeToFloat64(mhr.Min)
}

// GetMax returns the max value.
func (mhr MarketHoursRange) GetMax() float64 {
	return TimeToFloat64(mhr.Max)
}

// SetMin sets the min value.
func (mhr *MarketHoursRange) SetMin(min float64) {
	mhr.Min = Float64ToTime(min)
}

// SetMax sets the max value.
func (mhr *MarketHoursRange) SetMax(max float64) {
	mhr.Max = Float64ToTime(max)
}

// GetDelta gets the delta.
func (mhr MarketHoursRange) GetDelta() float64 {
	min := TimeToFloat64(mhr.Min)
	max := TimeToFloat64(mhr.Max)
	return max - min
}

// GetDomain gets the domain.
func (mhr MarketHoursRange) GetDomain() int {
	return mhr.Domain
}

// SetDomain sets the domain.
func (mhr *MarketHoursRange) SetDomain(domain int) {
	mhr.Domain = domain
}

// GetHolidayProvider coalesces a userprovided holiday provider and the date.DefaultHolidayProvider.
func (mhr MarketHoursRange) GetHolidayProvider() date.HolidayProvider {
	if mhr.HolidayProvider == nil {
		return date.DefaultHolidayProvider
	}
	return mhr.HolidayProvider
}

// GetTicks returns the ticks for the range.
// This is to override the default continous ticks that would be generated for the range.
func (mhr *MarketHoursRange) GetTicks(vf ValueFormatter) []Tick {
	// return one tick per day
	// figure out how to advance one ticke per market day.
	var ticks []Tick

	cursor := date.On(mhr.MarketClose, mhr.Min)
	maxClose := date.On(mhr.MarketClose, mhr.Max)
	for date.BeforeDate(cursor, maxClose) {
		if date.IsWeekDay(cursor.Weekday()) && !mhr.GetHolidayProvider()(cursor) {
			ticks = append(ticks, Tick{
				Value: TimeToFloat64(cursor),
				Label: vf(cursor),
			})
		}

		cursor = cursor.AddDate(0, 0, 1)
	}

	endMarketClose := date.On(mhr.MarketClose, cursor)
	if date.IsWeekDay(endMarketClose.Weekday()) && !mhr.GetHolidayProvider()(endMarketClose) {
		ticks = append(ticks, Tick{
			Value: TimeToFloat64(endMarketClose),
			Label: vf(endMarketClose),
		})
	}
	return ticks
}

func (mhr MarketHoursRange) String() string {
	return fmt.Sprintf("MarketHoursRange [%s, %s] => %d", mhr.Min.Format(DefaultDateMinuteFormat), mhr.Max.Format(DefaultDateMinuteFormat), mhr.Domain)
}

// Translate maps a given value into the ContinuousRange space.
func (mhr MarketHoursRange) Translate(value float64) int {
	valueTime := Float64ToTime(value)
	valueTimeEastern := valueTime.In(date.Eastern())
	deltaSeconds := date.CalculateMarketSecondsBetween(mhr.Min, mhr.Max, mhr.MarketOpen, mhr.MarketClose, mhr.HolidayProvider)
	valueDelta := date.CalculateMarketSecondsBetween(mhr.Min, valueTimeEastern, mhr.MarketOpen, mhr.MarketClose, mhr.HolidayProvider)
	translated := int((float64(valueDelta) / float64(deltaSeconds)) * float64(mhr.Domain))
	return translated
}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxdclient

import (
	"github.com/juju/errors"
)

// Config contains the config values used for a connection to the LXD API.
type Config struct {
	// Namespace identifies the namespace to associate with containers
	// and other resources with which the client interacts. It may be
	// blank.
	// TODO(jam) This doesn't appear to do much at the moment.
	Namespace string

	// Remote identifies the remote server to which the client should
	// connect. For the default "remote" use Local.
	Remote Remote
}

// WithDefaults updates a copy of the config with default values
// where needed.
func (cfg Config) WithDefaults() (Config, error) {
	// We leave a blank namespace alone.
	// Also, note that cfg is a value receiver, so it is an implicit copy.

	var err error
	cfg.Remote, err = cfg.Remote.WithDefaults()
	if err != nil {
		return cfg, errors.Trace(err)
	}
	return cfg, nil
}

// Validate checks the client's fields for invalid values.
func (cfg Config) Validate() error {
	// TODO(ericsnow) Check cfg.Namespace (if provided)?
	if err := cfg.Remote.Validate(); err != nil {
		return errors.Trace(err)
	}

	return nil
}

// UsingTCPRemote converts the config into a "non-local" version. An
// already non-local remote is left alone.
//
// For a "local" remote (see Local), the remote is changed to a one
// with the host set to the IP address of the local lxcbr0 bridge
// interface. The LXD server is also set up for remote access, exposing
// the TCP port and adding a certificate for remote access.
func (cfg Config) UsingTCPRemote() (Config, error) {
	// Note that cfg is a value receiver, so it is an implicit copy.

	if !cfg.Remote.isLocal() {
		return cfg, nil
	}

	remote, err := cfg.Remote.UsingTCP()
	if err != nil {
		return cfg, errors.Trace(err)
	}

	// Update the server config and authorized certs.
	serverCert, err := prepareRemote(cfg, *remote.Cert)
	if err != nil {
		return cfg, errors.Trace(err)
	}
	// Note: jam 2016-02-25 setting ServerPEMCert feels like something
	// that would have been done in UsingTCP. However, we can't know the
	// server's certificate until we've actually connected to it, which
	// happens in prepareRemote
	remote.ServerPEMCert = serverCert

	cfg.Remote = remote
	return cfg, nil
}

func prepareRemote(cfg Config, newCert Cert) (string, error) {
	client, err := Connect(cfg)
	if err != nil {
		return "", errors.Trace(err)
	}

	// Make sure the LXD service is configured to listen to local https
	// requests, rather than only via the Unix socket.
	// TODO: jam 2016-02-25 This tells LXD to listen on all addresses,
	// 	which does expose the LXD to outside requests. It would
	// 	probably be better to only tell LXD to listen for requests on
	// 	the loopback and LXC bridges that we are using.
	if err := client.SetConfig("core.https_address", "[::]"); err != nil {
		return "", errors.Trace(err)
	}

	// Make sure the LXD service will allow our certificate to connect
	if err := client.AddCert(newCert); err != nil {
		return "", errors.Trace(err)
	}

	st, err := client.ServerStatus()
	if err != nil {
		return "", errors.Trace(err)
	}

	return st.Environment.Certificate, nil
}
<commit_msg>lxd provider: fix lxdbr0 TOCTOU<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxdclient

import (
	"github.com/juju/errors"
)

// Config contains the config values used for a connection to the LXD API.
type Config struct {
	// Namespace identifies the namespace to associate with containers
	// and other resources with which the client interacts. It may be
	// blank.
	// TODO(jam) This doesn't appear to do much at the moment.
	Namespace string

	// Remote identifies the remote server to which the client should
	// connect. For the default "remote" use Local.
	Remote Remote
}

// WithDefaults updates a copy of the config with default values
// where needed.
func (cfg Config) WithDefaults() (Config, error) {
	// We leave a blank namespace alone.
	// Also, note that cfg is a value receiver, so it is an implicit copy.

	var err error
	cfg.Remote, err = cfg.Remote.WithDefaults()
	if err != nil {
		return cfg, errors.Trace(err)
	}
	return cfg, nil
}

// Validate checks the client's fields for invalid values.
func (cfg Config) Validate() error {
	// TODO(ericsnow) Check cfg.Namespace (if provided)?
	if err := cfg.Remote.Validate(); err != nil {
		return errors.Trace(err)
	}

	return nil
}

// UsingTCPRemote converts the config into a "non-local" version. An
// already non-local remote is left alone.
//
// For a "local" remote (see Local), the remote is changed to a one
// with the host set to the IP address of the local lxcbr0 bridge
// interface. The LXD server is also set up for remote access, exposing
// the TCP port and adding a certificate for remote access.
func (cfg Config) UsingTCPRemote() (Config, error) {
	// Note that cfg is a value receiver, so it is an implicit copy.

	if !cfg.Remote.isLocal() {
		return cfg, nil
	}

	/* Here, we rely on the fact that Connect() does a ServerStatus.
	 * UsingTCP will try to figure out the network name of the lxdbr0,
	 * which means that lxdbr0 needs to be up. If this lxd has never had
	 * anything done to it, it hasn't been socket activated yet, and lxdbr0
	 * won't exist. So, we rely on this poke to get lxdbr0 started.
	 */
	client, err := Connect(cfg)
	if err != nil {
		return cfg, errors.Trace(err)
	}

	remote, err := cfg.Remote.UsingTCP()
	if err != nil {
		return cfg, errors.Trace(err)
	}

	// Update the server config and authorized certs.
	serverCert, err := prepareRemote(client, *remote.Cert)
	if err != nil {
		return cfg, errors.Trace(err)
	}
	// Note: jam 2016-02-25 setting ServerPEMCert feels like something
	// that would have been done in UsingTCP. However, we can't know the
	// server's certificate until we've actually connected to it, which
	// happens in prepareRemote
	remote.ServerPEMCert = serverCert

	cfg.Remote = remote
	return cfg, nil
}

func prepareRemote(client *Client, newCert Cert) (string, error) {
	// Make sure the LXD service is configured to listen to local https
	// requests, rather than only via the Unix socket.
	// TODO: jam 2016-02-25 This tells LXD to listen on all addresses,
	// 	which does expose the LXD to outside requests. It would
	// 	probably be better to only tell LXD to listen for requests on
	// 	the loopback and LXC bridges that we are using.
	if err := client.SetConfig("core.https_address", "[::]"); err != nil {
		return "", errors.Trace(err)
	}

	// Make sure the LXD service will allow our certificate to connect
	if err := client.AddCert(newCert); err != nil {
		return "", errors.Trace(err)
	}

	st, err := client.ServerStatus()
	if err != nil {
		return "", errors.Trace(err)
	}

	return st.Environment.Certificate, nil
}
<|endoftext|>


<commit_before>package glacier

import (
	"fmt"
	"github.com/rdwilliamson/aws"
	"testing"
)

func TestList(t *testing.T) {
	secret, access := aws.KeysFromEnviroment()
	connection := NewConnection(secret, access, aws.USEast)
	_, result, err := connection.ListVaults(1000, "")
	if err != nil {
		t.Fatal(err)
	}
	fmt.Println(result)
}
<commit_msg>Removed vault test because it actually sends a request to amazon.<commit_after><|endoftext|>