<commit_before>//go:generate counterfeiter deployment_install_client.go InstallStrategyDeploymentInterface
package wrappers

import (
	"github.com/pkg/errors"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"

	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
)

var ErrNilObject = errors.New("Bad object supplied: <nil>")

type InstallStrategyDeploymentInterface interface {
	CreateRole(role *rbacv1.Role) (*rbacv1.Role, error)
	CreateRoleBinding(roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)
	EnsureServiceAccount(serviceAccount *corev1.ServiceAccount, owner ownerutil.Owner) (*corev1.ServiceAccount, error)
	CreateDeployment(deployment *appsv1.Deployment) (*appsv1.Deployment, error)
	CreateOrUpdateDeployment(deployment *appsv1.Deployment) (*appsv1.Deployment, error)
	DeleteDeployment(name string) error
	GetServiceAccountByName(serviceAccountName string) (*corev1.ServiceAccount, error)
	FindAnyDeploymentsMatchingNames(depNames []string) ([]*appsv1.Deployment, error)
	FindAnyDeploymentsMatchingLabels(label labels.Selector) ([]*appsv1.Deployment, error)
}

type InstallStrategyDeploymentClientForNamespace struct {
	opClient  operatorclient.ClientInterface
	opLister  operatorlister.OperatorLister
	Namespace string
}

var _ InstallStrategyDeploymentInterface = &InstallStrategyDeploymentClientForNamespace{}

func NewInstallStrategyDeploymentClient(opClient operatorclient.ClientInterface, opLister operatorlister.OperatorLister, namespace string) InstallStrategyDeploymentInterface {
	return &InstallStrategyDeploymentClientForNamespace{
		opClient:  opClient,
		opLister:  opLister,
		Namespace: namespace,
	}
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateRole(role *rbacv1.Role) (*rbacv1.Role, error) {
	return c.opClient.KubernetesInterface().RbacV1().Roles(c.Namespace).Create(role)
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateRoleBinding(roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error) {
	return c.opClient.KubernetesInterface().RbacV1().RoleBindings(c.Namespace).Create(roleBinding)
}

func (c *InstallStrategyDeploymentClientForNamespace) EnsureServiceAccount(serviceAccount *corev1.ServiceAccount, owner ownerutil.Owner) (*corev1.ServiceAccount, error) {
	if serviceAccount == nil {
		return nil, ErrNilObject
	}

	foundAccount, err := c.opLister.CoreV1().ServiceAccountLister().ServiceAccounts(c.Namespace).Get(serviceAccount.Name)
	if err != nil && !apierrors.IsNotFound(err) {
		return nil, errors.Wrap(err, "checking for existing serviceacccount failed")
	}

	// create if not found
	if err != nil && apierrors.IsNotFound(err) {
		serviceAccount.SetNamespace(c.Namespace)
		createdAccount, err := c.opClient.CreateServiceAccount(serviceAccount)
		if err != nil && !apierrors.IsAlreadyExists(err) {
			return nil, errors.Wrap(err, "creating serviceacccount failed")
		}
		if apierrors.IsAlreadyExists(err) {
			return serviceAccount, nil
		}
		return createdAccount, nil
	}

	// if found, ensure ownerreferences
	if ownerutil.IsOwnedBy(foundAccount, owner) {
		return foundAccount, nil
	}
	// set owner if missing
	ownerutil.AddNonBlockingOwner(foundAccount, owner)
	return c.opClient.UpdateServiceAccount(foundAccount)
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateDeployment(deployment *appsv1.Deployment) (*appsv1.Deployment, error) {
	return c.opClient.CreateDeployment(deployment)
}

func (c *InstallStrategyDeploymentClientForNamespace) DeleteDeployment(name string) error {
	foregroundDelete := metav1.DeletePropagationForeground // cascading delete
	immediate := int64(0)
	immediateForegroundDelete := &metav1.DeleteOptions{GracePeriodSeconds: &immediate, PropagationPolicy: &foregroundDelete}
	return c.opClient.DeleteDeployment(c.Namespace, name, immediateForegroundDelete)
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateOrUpdateDeployment(deployment *appsv1.Deployment) (*appsv1.Deployment, error) {
	d, _, err := c.opClient.CreateOrRollingUpdateDeployment(deployment)
	return d, err
}

func (c *InstallStrategyDeploymentClientForNamespace) GetServiceAccountByName(serviceAccountName string) (*corev1.ServiceAccount, error) {
	return c.opLister.CoreV1().ServiceAccountLister().ServiceAccounts(c.Namespace).Get(serviceAccountName)
}

func (c *InstallStrategyDeploymentClientForNamespace) FindAnyDeploymentsMatchingNames(depNames []string) ([]*appsv1.Deployment, error) {
	var deployments []*appsv1.Deployment
	for _, depName := range depNames {
		fetchedDep, err := c.opLister.AppsV1().DeploymentLister().Deployments(c.Namespace).Get(depName)
		if err == nil {
			deployments = append(deployments, fetchedDep)
		} else {
			// Any errors other than !exists are propagated up
			if !apierrors.IsNotFound(err) {
				return deployments, err
			}
		}
	}
	return deployments, nil
}

func (c *InstallStrategyDeploymentClientForNamespace) FindAnyDeploymentsMatchingLabels(label labels.Selector) ([]*appsv1.Deployment, error) {
	deployments, err := c.opLister.AppsV1().DeploymentLister().Deployments(c.Namespace).List(label)
	// Any errors other than !exists are propagated up
	if err != nil && !apierrors.IsNotFound(err) {
		return nil, err
	}

	return deployments, nil
}
<commit_msg>fix(olm): List does not return NotFound error<commit_after>//go:generate counterfeiter deployment_install_client.go InstallStrategyDeploymentInterface
package wrappers

import (
	"github.com/pkg/errors"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"

	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
)

var ErrNilObject = errors.New("Bad object supplied: <nil>")

type InstallStrategyDeploymentInterface interface {
	CreateRole(role *rbacv1.Role) (*rbacv1.Role, error)
	CreateRoleBinding(roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)
	EnsureServiceAccount(serviceAccount *corev1.ServiceAccount, owner ownerutil.Owner) (*corev1.ServiceAccount, error)
	CreateDeployment(deployment *appsv1.Deployment) (*appsv1.Deployment, error)
	CreateOrUpdateDeployment(deployment *appsv1.Deployment) (*appsv1.Deployment, error)
	DeleteDeployment(name string) error
	GetServiceAccountByName(serviceAccountName string) (*corev1.ServiceAccount, error)
	FindAnyDeploymentsMatchingNames(depNames []string) ([]*appsv1.Deployment, error)
	FindAnyDeploymentsMatchingLabels(label labels.Selector) ([]*appsv1.Deployment, error)
}

type InstallStrategyDeploymentClientForNamespace struct {
	opClient  operatorclient.ClientInterface
	opLister  operatorlister.OperatorLister
	Namespace string
}

var _ InstallStrategyDeploymentInterface = &InstallStrategyDeploymentClientForNamespace{}

func NewInstallStrategyDeploymentClient(opClient operatorclient.ClientInterface, opLister operatorlister.OperatorLister, namespace string) InstallStrategyDeploymentInterface {
	return &InstallStrategyDeploymentClientForNamespace{
		opClient:  opClient,
		opLister:  opLister,
		Namespace: namespace,
	}
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateRole(role *rbacv1.Role) (*rbacv1.Role, error) {
	return c.opClient.KubernetesInterface().RbacV1().Roles(c.Namespace).Create(role)
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateRoleBinding(roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error) {
	return c.opClient.KubernetesInterface().RbacV1().RoleBindings(c.Namespace).Create(roleBinding)
}

func (c *InstallStrategyDeploymentClientForNamespace) EnsureServiceAccount(serviceAccount *corev1.ServiceAccount, owner ownerutil.Owner) (*corev1.ServiceAccount, error) {
	if serviceAccount == nil {
		return nil, ErrNilObject
	}

	foundAccount, err := c.opLister.CoreV1().ServiceAccountLister().ServiceAccounts(c.Namespace).Get(serviceAccount.Name)
	if err != nil && !apierrors.IsNotFound(err) {
		return nil, errors.Wrap(err, "checking for existing serviceacccount failed")
	}

	// create if not found
	if err != nil && apierrors.IsNotFound(err) {
		serviceAccount.SetNamespace(c.Namespace)
		createdAccount, err := c.opClient.CreateServiceAccount(serviceAccount)
		if err != nil && !apierrors.IsAlreadyExists(err) {
			return nil, errors.Wrap(err, "creating serviceacccount failed")
		}
		if apierrors.IsAlreadyExists(err) {
			return serviceAccount, nil
		}
		return createdAccount, nil
	}

	// if found, ensure ownerreferences
	if ownerutil.IsOwnedBy(foundAccount, owner) {
		return foundAccount, nil
	}
	// set owner if missing
	ownerutil.AddNonBlockingOwner(foundAccount, owner)
	return c.opClient.UpdateServiceAccount(foundAccount)
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateDeployment(deployment *appsv1.Deployment) (*appsv1.Deployment, error) {
	return c.opClient.CreateDeployment(deployment)
}

func (c *InstallStrategyDeploymentClientForNamespace) DeleteDeployment(name string) error {
	foregroundDelete := metav1.DeletePropagationForeground // cascading delete
	immediate := int64(0)
	immediateForegroundDelete := &metav1.DeleteOptions{GracePeriodSeconds: &immediate, PropagationPolicy: &foregroundDelete}
	return c.opClient.DeleteDeployment(c.Namespace, name, immediateForegroundDelete)
}

func (c *InstallStrategyDeploymentClientForNamespace) CreateOrUpdateDeployment(deployment *appsv1.Deployment) (*appsv1.Deployment, error) {
	d, _, err := c.opClient.CreateOrRollingUpdateDeployment(deployment)
	return d, err
}

func (c *InstallStrategyDeploymentClientForNamespace) GetServiceAccountByName(serviceAccountName string) (*corev1.ServiceAccount, error) {
	return c.opLister.CoreV1().ServiceAccountLister().ServiceAccounts(c.Namespace).Get(serviceAccountName)
}

func (c *InstallStrategyDeploymentClientForNamespace) FindAnyDeploymentsMatchingNames(depNames []string) ([]*appsv1.Deployment, error) {
	var deployments []*appsv1.Deployment
	for _, depName := range depNames {
		fetchedDep, err := c.opLister.AppsV1().DeploymentLister().Deployments(c.Namespace).Get(depName)
		if err == nil {
			deployments = append(deployments, fetchedDep)
		} else {
			// Any errors other than !exists are propagated up
			if !apierrors.IsNotFound(err) {
				return deployments, err
			}
		}
	}
	return deployments, nil
}

func (c *InstallStrategyDeploymentClientForNamespace) FindAnyDeploymentsMatchingLabels(label labels.Selector) ([]*appsv1.Deployment, error) {
	deployments, err := c.opLister.AppsV1().DeploymentLister().Deployments(c.Namespace).List(label)
	if err != nil {
		return nil, err
	}

	return deployments, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package cpumanager

import (
	"k8s.io/api/core/v1"
	"k8s.io/klog/v2"
	"k8s.io/kubernetes/pkg/kubelet/cm/containermap"
	"k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state"
	"k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
	"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager"
	"k8s.io/kubernetes/pkg/kubelet/config"
	"k8s.io/kubernetes/pkg/kubelet/status"
)

type fakeManager struct {
	state state.State
}

func (m *fakeManager) Start(activePods ActivePodsFunc, sourcesReady config.SourcesReady, podStatusProvider status.PodStatusProvider, containerRuntime runtimeService, initialContainers containermap.ContainerMap) error {
	klog.Info("[fake cpumanager] Start()")
	return nil
}

func (m *fakeManager) Policy() Policy {
	klog.Info("[fake cpumanager] Policy()")
	return NewNonePolicy()
}

func (m *fakeManager) Allocate(pod *v1.Pod, container *v1.Container) error {
	klog.Infof("[fake cpumanager] Allocate (pod: %s, container: %s", pod.Name, container.Name)
	return nil
}

func (m *fakeManager) AddContainer(pod *v1.Pod, container *v1.Container, containerID string) {
	klog.Infof("[fake cpumanager] AddContainer (pod: %s, container: %s, container id: %s)", pod.Name, container.Name, containerID)
}

func (m *fakeManager) RemoveContainer(containerID string) error {
	klog.Infof("[fake cpumanager] RemoveContainer (container id: %s)", containerID)
	return nil
}

func (m *fakeManager) GetTopologyHints(pod *v1.Pod, container *v1.Container) map[string][]topologymanager.TopologyHint {
	klog.Infof("[fake cpumanager] Get Container Topology Hints")
	return map[string][]topologymanager.TopologyHint{}
}

func (m *fakeManager) GetPodTopologyHints(pod *v1.Pod) map[string][]topologymanager.TopologyHint {
	klog.Infof("[fake cpumanager] Get Pod Topology Hints")
	return map[string][]topologymanager.TopologyHint{}
}

func (m *fakeManager) State() state.Reader {
	return m.state
}

func (m *fakeManager) GetCPUs(podUID, containerName string) cpuset.CPUSet {
	klog.Infof("[fake cpumanager] GetCPUs(podUID: %s, containerName: %s)", podUID, containerName)
	return cpuset.CPUSet{}
}

func (m *fakeManager) GetAllocatableCPUs() cpuset.CPUSet {
	klog.Infof("[fake cpumanager] Get Allocatable Cpus")
	return cpuset.CPUSet{}
}

// NewFakeManager creates empty/fake cpu manager
func NewFakeManager() Manager {
	return &fakeManager{
		state: state.NewMemoryState(),
	}
}
<commit_msg>update structured log for fake_cpu_manager.go<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package cpumanager

import (
	"k8s.io/api/core/v1"
	"k8s.io/klog/v2"
	"k8s.io/kubernetes/pkg/kubelet/cm/containermap"
	"k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state"
	"k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
	"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager"
	"k8s.io/kubernetes/pkg/kubelet/config"
	"k8s.io/kubernetes/pkg/kubelet/status"
)

type fakeManager struct {
	state state.State
}

func (m *fakeManager) Start(activePods ActivePodsFunc, sourcesReady config.SourcesReady, podStatusProvider status.PodStatusProvider, containerRuntime runtimeService, initialContainers containermap.ContainerMap) error {
	klog.Info("Start()")
	return nil
}

func (m *fakeManager) Policy() Policy {
	klog.InfoS("Policy()")
	return NewNonePolicy()
}

func (m *fakeManager) Allocate(pod *v1.Pod, container *v1.Container) error {
	klog.InfoS("Allocate", "pod", klog.KObj(pod), "containerName", container.Name)
	return nil
}

func (m *fakeManager) AddContainer(pod *v1.Pod, container *v1.Container, containerID string) {
	klog.InfoS("AddContainer", "pod", klog.KObj(pod), "containerName", container.Name, "containerID", containerID)
}

func (m *fakeManager) RemoveContainer(containerID string) error {
	klog.InfoS("RemoveContainer", "containerID", containerID)
	return nil
}

func (m *fakeManager) GetTopologyHints(pod *v1.Pod, container *v1.Container) map[string][]topologymanager.TopologyHint {
	klog.InfoS("Get Container Topology Hints")
	return map[string][]topologymanager.TopologyHint{}
}

func (m *fakeManager) GetPodTopologyHints(pod *v1.Pod) map[string][]topologymanager.TopologyHint {
	klog.InfoS("Get Pod Topology Hints")
	return map[string][]topologymanager.TopologyHint{}
}

func (m *fakeManager) State() state.Reader {
	return m.state
}

func (m *fakeManager) GetCPUs(podUID, containerName string) cpuset.CPUSet {
	klog.InfoS("GetCPUs", "podUID", podUID, "containerName", container.Name)
	return cpuset.CPUSet{}
}

func (m *fakeManager) GetAllocatableCPUs() cpuset.CPUSet {
	klog.InfoS("Get Allocatable Cpus")
	return cpuset.CPUSet{}
}

// NewFakeManager creates empty/fake cpu manager
func NewFakeManager() Manager {
	return &fakeManager{
		state: state.NewMemoryState(),
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package components

import (
	"fmt"
	"time"

	"github.com/golang/glog"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/pkg/apis/kops/util"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/cloudup/gce"
	"k8s.io/kops/upup/pkg/fi/loader"
)

const (
	defaultAttachDetachReconcileSyncPeriod = time.Minute
)

// KubeControllerManagerOptionsBuilder adds options for the kubernetes controller manager to the model.
type KubeControllerManagerOptionsBuilder struct {
	Context *OptionsContext
}

var _ loader.OptionsBuilder = &KubeControllerManagerOptionsBuilder{}

// BuildOptions generates the configurations used to create kubernetes controller manager manifest
func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error {

	clusterSpec := o.(*kops.ClusterSpec)
	if clusterSpec.KubeControllerManager == nil {
		clusterSpec.KubeControllerManager = &kops.KubeControllerManagerConfig{}
	}
	kcm := clusterSpec.KubeControllerManager

	k8sv148, err := util.ParseKubernetesVersion("v1.4.8")
	if err != nil {
		return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
	}

	k8sv152, err := util.ParseKubernetesVersion("v1.5.2")
	if err != nil {
		return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
	}

	kubernetesVersion, err := KubernetesVersion(clusterSpec)
	if err != nil {
		return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
	}

	// In 1.4.8+ and 1.5.2+ k8s added the capability to tune the duration upon which the volume attach detach
	// component is called.
	// See https://github.com/kubernetes/kubernetes/pull/39551
	// TLDR; set this too low, and have a few EBS Volumes, and you will spam AWS api

	// if 1.4.8+ and 1.5.2+
	if (kubernetesVersion.GTE(*k8sv148) && kubernetesVersion.Minor == 4) || kubernetesVersion.GTE(*k8sv152) {
		glog.V(4).Infof("Kubernetes version %q supports AttachDetachReconcileSyncPeriod; will configure", kubernetesVersion)
		// If not set ... or set to 0s ... which is stupid
		if kcm.AttachDetachReconcileSyncPeriod == nil ||
			kcm.AttachDetachReconcileSyncPeriod.Duration.String() == "0s" {

			glog.V(8).Infof("AttachDetachReconcileSyncPeriod is not set; will set to default %v", defaultAttachDetachReconcileSyncPeriod)
			kcm.AttachDetachReconcileSyncPeriod = &metav1.Duration{Duration: defaultAttachDetachReconcileSyncPeriod}

			// If less than 1 min and greater than 1 sec ... you get a warning
		} else if kcm.AttachDetachReconcileSyncPeriod.Duration < defaultAttachDetachReconcileSyncPeriod &&
			kcm.AttachDetachReconcileSyncPeriod.Duration > time.Second {

			glog.Infof("KubeControllerManager AttachDetachReconcileSyncPeriod is set lower than recommended: %s", defaultAttachDetachReconcileSyncPeriod)

			// If less than 1sec you get an error.  Controller is coded to not allow configuration
			// less than one second.
		} else if kcm.AttachDetachReconcileSyncPeriod.Duration < time.Second {
			return fmt.Errorf("AttachDetachReconcileSyncPeriod cannot be set to less than 1 second")
		}
	} else {
		glog.V(4).Infof("not setting AttachDetachReconcileSyncPeriod, k8s version is too low")
		kcm.AttachDetachReconcileSyncPeriod = nil
	}

	kcm.ClusterName = b.Context.ClusterName
	switch kops.CloudProviderID(clusterSpec.CloudProvider) {
	case kops.CloudProviderAWS:
		kcm.CloudProvider = "aws"

	case kops.CloudProviderGCE:
		kcm.CloudProvider = "gce"
		kcm.ClusterName = gce.SafeClusterName(b.Context.ClusterName)

	case kops.CloudProviderDO:
		kcm.CloudProvider = "external"

	case kops.CloudProviderVSphere:
		kcm.CloudProvider = "vsphere"

	case kops.CloudProviderBareMetal:
		// No cloudprovider

	case kops.CloudProviderOpenstack:
		kcm.CloudProvider = "openstack"

	default:
		return fmt.Errorf("unknown cloudprovider %q", clusterSpec.CloudProvider)
	}

	if clusterSpec.ExternalCloudControllerManager != nil {
		kcm.CloudProvider = "external"
	}

	if kcm.Master == "" {
		if b.Context.IsKubernetesLT("1.6") {
			// As of 1.6, we find the master using kubeconfig
			kcm.Master = "127.0.0.1:8080"
		}
	}

	kcm.LogLevel = 2

	image, err := Image("kube-controller-manager", clusterSpec, b.Context.AssetBuilder)
	if err != nil {
		return err
	}
	kcm.Image = image

	// Doesn't seem to be any real downside to always doing a leader election
	kcm.LeaderElection = &kops.LeaderElectionConfiguration{LeaderElect: fi.Bool(true)}

	kcm.AllocateNodeCIDRs = fi.Bool(true)
	kcm.ConfigureCloudRoutes = fi.Bool(false)

	networking := clusterSpec.Networking
	if networking == nil || networking.Classic != nil {
		kcm.ConfigureCloudRoutes = fi.Bool(true)
	} else if networking.Kubenet != nil {
		kcm.ConfigureCloudRoutes = fi.Bool(true)
	} else if networking.External != nil {
		kcm.ConfigureCloudRoutes = fi.Bool(false)
	} else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != nil || networking.AmazonVPC != nil || networking.Cilium != nil {
		kcm.ConfigureCloudRoutes = fi.Bool(false)
	} else if networking.Kopeio != nil {
		// Kopeio is based on kubenet / external
		kcm.ConfigureCloudRoutes = fi.Bool(false)
	} else {
		return fmt.Errorf("no networking mode set")
	}

	if kcm.UseServiceAccountCredentials == nil {
		if b.Context.IsKubernetesGTE("1.6") {
			kcm.UseServiceAccountCredentials = fi.Bool(true)
		}
	}

	return nil
}
<commit_msg>- enabling the tokencleaner controller when bootstrap tokens are enabled<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package components

import (
	"fmt"
	"time"

	"github.com/golang/glog"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/pkg/apis/kops/util"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/cloudup/gce"
	"k8s.io/kops/upup/pkg/fi/loader"
)

const (
	defaultAttachDetachReconcileSyncPeriod = time.Minute
)

// KubeControllerManagerOptionsBuilder adds options for the kubernetes controller manager to the model.
type KubeControllerManagerOptionsBuilder struct {
	Context *OptionsContext
}

var _ loader.OptionsBuilder = &KubeControllerManagerOptionsBuilder{}

// BuildOptions generates the configurations used to create kubernetes controller manager manifest
func (b *KubeControllerManagerOptionsBuilder) BuildOptions(o interface{}) error {

	clusterSpec := o.(*kops.ClusterSpec)
	if clusterSpec.KubeControllerManager == nil {
		clusterSpec.KubeControllerManager = &kops.KubeControllerManagerConfig{}
	}
	kcm := clusterSpec.KubeControllerManager

	k8sv148, err := util.ParseKubernetesVersion("v1.4.8")
	if err != nil {
		return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
	}

	k8sv152, err := util.ParseKubernetesVersion("v1.5.2")
	if err != nil {
		return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
	}

	kubernetesVersion, err := KubernetesVersion(clusterSpec)
	if err != nil {
		return fmt.Errorf("Unable to parse kubernetesVersion %s", err)
	}

	// In 1.4.8+ and 1.5.2+ k8s added the capability to tune the duration upon which the volume attach detach
	// component is called.
	// See https://github.com/kubernetes/kubernetes/pull/39551
	// TLDR; set this too low, and have a few EBS Volumes, and you will spam AWS api

	// if 1.4.8+ and 1.5.2+
	if (kubernetesVersion.GTE(*k8sv148) && kubernetesVersion.Minor == 4) || kubernetesVersion.GTE(*k8sv152) {
		glog.V(4).Infof("Kubernetes version %q supports AttachDetachReconcileSyncPeriod; will configure", kubernetesVersion)
		// If not set ... or set to 0s ... which is stupid
		if kcm.AttachDetachReconcileSyncPeriod == nil ||
			kcm.AttachDetachReconcileSyncPeriod.Duration.String() == "0s" {

			glog.V(8).Infof("AttachDetachReconcileSyncPeriod is not set; will set to default %v", defaultAttachDetachReconcileSyncPeriod)
			kcm.AttachDetachReconcileSyncPeriod = &metav1.Duration{Duration: defaultAttachDetachReconcileSyncPeriod}

			// If less than 1 min and greater than 1 sec ... you get a warning
		} else if kcm.AttachDetachReconcileSyncPeriod.Duration < defaultAttachDetachReconcileSyncPeriod &&
			kcm.AttachDetachReconcileSyncPeriod.Duration > time.Second {

			glog.Infof("KubeControllerManager AttachDetachReconcileSyncPeriod is set lower than recommended: %s", defaultAttachDetachReconcileSyncPeriod)

			// If less than 1sec you get an error.  Controller is coded to not allow configuration
			// less than one second.
		} else if kcm.AttachDetachReconcileSyncPeriod.Duration < time.Second {
			return fmt.Errorf("AttachDetachReconcileSyncPeriod cannot be set to less than 1 second")
		}
	} else {
		glog.V(4).Infof("not setting AttachDetachReconcileSyncPeriod, k8s version is too low")
		kcm.AttachDetachReconcileSyncPeriod = nil
	}

	kcm.ClusterName = b.Context.ClusterName
	switch kops.CloudProviderID(clusterSpec.CloudProvider) {
	case kops.CloudProviderAWS:
		kcm.CloudProvider = "aws"

	case kops.CloudProviderGCE:
		kcm.CloudProvider = "gce"
		kcm.ClusterName = gce.SafeClusterName(b.Context.ClusterName)

	case kops.CloudProviderDO:
		kcm.CloudProvider = "external"

	case kops.CloudProviderVSphere:
		kcm.CloudProvider = "vsphere"

	case kops.CloudProviderBareMetal:
		// No cloudprovider

	case kops.CloudProviderOpenstack:
		kcm.CloudProvider = "openstack"

	default:
		return fmt.Errorf("unknown cloudprovider %q", clusterSpec.CloudProvider)
	}

	if clusterSpec.ExternalCloudControllerManager != nil {
		kcm.CloudProvider = "external"
	}

	if kcm.Master == "" {
		if b.Context.IsKubernetesLT("1.6") {
			// As of 1.6, we find the master using kubeconfig
			kcm.Master = "127.0.0.1:8080"
		}
	}

	kcm.LogLevel = 2

	image, err := Image("kube-controller-manager", clusterSpec, b.Context.AssetBuilder)
	if err != nil {
		return err
	}
	kcm.Image = image

	// Doesn't seem to be any real downside to always doing a leader election
	kcm.LeaderElection = &kops.LeaderElectionConfiguration{LeaderElect: fi.Bool(true)}

	kcm.AllocateNodeCIDRs = fi.Bool(true)
	kcm.ConfigureCloudRoutes = fi.Bool(false)

	networking := clusterSpec.Networking
	if networking == nil || networking.Classic != nil {
		kcm.ConfigureCloudRoutes = fi.Bool(true)
	} else if networking.Kubenet != nil {
		kcm.ConfigureCloudRoutes = fi.Bool(true)
	} else if networking.External != nil {
		kcm.ConfigureCloudRoutes = fi.Bool(false)
	} else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != nil || networking.AmazonVPC != nil || networking.Cilium != nil {
		kcm.ConfigureCloudRoutes = fi.Bool(false)
	} else if networking.Kopeio != nil {
		// Kopeio is based on kubenet / external
		kcm.ConfigureCloudRoutes = fi.Bool(false)
	} else {
		return fmt.Errorf("no networking mode set")
	}

	if kcm.UseServiceAccountCredentials == nil {
		if b.Context.IsKubernetesGTE("1.6") {
			kcm.UseServiceAccountCredentials = fi.Bool(true)
		}
	}

	// @check if the node authorization is enabled and if so enable the tokencleaner controller (disabled by default)
	// This is responsible for cleaning up bootstrap tokens which have expired
	if b.Context.IsKubernetesGTE("1.10") {
		if fi.BoolValue(clusterSpec.KubeAPIServer.EnableBootstrapAuthToken) && len(kcm.Controllers) <= 0 {
			kcm.Controllers = []string{"*", "tokencleaner"}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package consul

import (
	"fmt"
	"time"

	"github.com/armon/go-metrics"
	"github.com/hashicorp/consul/consul/structs"
)

// KVS endpoint is used to manipulate the Key-Value store
type KVS struct {
	srv *Server
}

// Apply is used to apply a KVS request to the data store. This should
// only be used for operations that modify the data
func (k *KVS) Apply(args *structs.KVSRequest, reply *bool) error {
	if done, err := k.srv.forward("KVS.Apply", args, args, reply); done {
		return err
	}
	defer metrics.MeasureSince([]string{"consul", "kvs", "apply"}, time.Now())

	// Verify the args
	if args.DirEnt.Key == "" && args.Op != structs.KVSDeleteTree {
		return fmt.Errorf("Must provide key")
	}

	// Apply the ACL policy if any
	acl, err := k.srv.resolveToken(args.Token)
	if err != nil {
		return err
	} else if acl != nil {
		switch args.Op {
		case structs.KVSDeleteTree:
			if !acl.KeyWritePrefix(args.DirEnt.Key) {
				return permissionDeniedErr
			}
		default:
			if !acl.KeyWrite(args.DirEnt.Key) {
				return permissionDeniedErr
			}
		}
	}

	// If this is a lock, we must check for a lock-delay. Since lock-delay
	// is based on wall-time, each peer expire the lock-delay at a slightly
	// different time. This means the enforcement of lock-delay cannot be done
	// after the raft log is committed as it would lead to inconsistent FSMs.
	// Instead, the lock-delay must be enforced before commit. This means that
	// only the wall-time of the leader node is used, preventing any inconsistencies.
	if args.Op == structs.KVSLock {
		state := k.srv.fsm.State()
		expires := state.KVSLockDelay(args.DirEnt.Key)
		if expires.After(time.Now()) {
			k.srv.logger.Printf("[WARN] consul.kvs: Rejecting lock of %s due to lock-delay until %v",
				args.DirEnt.Key, expires)
			*reply = false
			return nil
		}
	}

	// Apply the update
	resp, err := k.srv.raftApply(structs.KVSRequestType, args)
	if err != nil {
		k.srv.logger.Printf("[ERR] consul.kvs: Apply failed: %v", err)
		return err
	}
	if respErr, ok := resp.(error); ok {
		return respErr
	}

	// Check if the return type is a bool
	if respBool, ok := resp.(bool); ok {
		*reply = respBool
	}
	return nil
}

// Get is used to lookup a single key
func (k *KVS) Get(args *structs.KeyRequest, reply *structs.IndexedDirEntries) error {
	if done, err := k.srv.forward("KVS.Get", args, args, reply); done {
		return err
	}

	acl, err := k.srv.resolveToken(args.Token)
	if err != nil {
		return err
	}

	// Get the local state
	state := k.srv.fsm.State()
	return k.srv.blockingRPC(&args.QueryOptions,
		&reply.QueryMeta,
		state.QueryTables("KVSGet"),
		func() error {
			index, ent, err := state.KVSGet(args.Key)
			if err != nil {
				return err
			}
			if acl != nil && !acl.KeyRead(args.Key) {
				ent = nil
			}
			if ent == nil {
				// Must provide non-zero index to prevent blocking
				// Index 1 is impossible anyways (due to Raft internals)
				if index == 0 {
					reply.Index = 1
				} else {
					reply.Index = index
				}
				reply.Entries = nil
			} else {
				reply.Index = ent.ModifyIndex
				reply.Entries = structs.DirEntries{ent}
			}
			return nil
		})
}

// List is used to list all keys with a given prefix
func (k *KVS) List(args *structs.KeyRequest, reply *structs.IndexedDirEntries) error {
	if done, err := k.srv.forward("KVS.List", args, args, reply); done {
		return err
	}

	acl, err := k.srv.resolveToken(args.Token)
	if err != nil {
		return err
	}

	// Get the local state
	state := k.srv.fsm.State()
	return k.srv.blockingRPC(&args.QueryOptions,
		&reply.QueryMeta,
		state.QueryTables("KVSList"),
		func() error {
			tombIndex, index, ent, err := state.KVSList(args.Key)
			if err != nil {
				return err
			}
			if acl != nil {
				ent = FilterDirEnt(acl, ent)
			}

			// Determine the maximum affected index
			var maxIndex uint64
			for _, e := range ent {
				if e.ModifyIndex > maxIndex {
					maxIndex = e.ModifyIndex
				}
			}
			if tombIndex > maxIndex {
				maxIndex = tombIndex
			}
			// Must provide non-zero index to prevent blocking
			// Index 1 is impossible anyways (due to Raft internals)
			if maxIndex == 0 {
				if index > 0 {
					maxIndex = index
				} else {
					maxIndex = 1
				}
			}
			reply.Index = maxIndex

			if len(ent) != 0 {
				reply.Entries = ent
			}
			return nil
		})
}

// ListKeys is used to list all keys with a given prefix to a seperator
func (k *KVS) ListKeys(args *structs.KeyListRequest, reply *structs.IndexedKeyList) error {
	if done, err := k.srv.forward("KVS.ListKeys", args, args, reply); done {
		return err
	}

	acl, err := k.srv.resolveToken(args.Token)
	if err != nil {
		return err
	}

	// Get the local state
	state := k.srv.fsm.State()
	return k.srv.blockingRPC(&args.QueryOptions,
		&reply.QueryMeta,
		state.QueryTables("KVSListKeys"),
		func() error {
			index, keys, err := state.KVSListKeys(args.Prefix, args.Seperator)
			reply.Index = index
			if acl != nil {
				keys = FilterKeys(acl, keys)
			}
			reply.Keys = keys
			return err
		})
}
<commit_msg>consul: Reverting some index compute logic<commit_after>package consul

import (
	"fmt"
	"time"

	"github.com/armon/go-metrics"
	"github.com/hashicorp/consul/consul/structs"
)

// KVS endpoint is used to manipulate the Key-Value store
type KVS struct {
	srv *Server
}

// Apply is used to apply a KVS request to the data store. This should
// only be used for operations that modify the data
func (k *KVS) Apply(args *structs.KVSRequest, reply *bool) error {
	if done, err := k.srv.forward("KVS.Apply", args, args, reply); done {
		return err
	}
	defer metrics.MeasureSince([]string{"consul", "kvs", "apply"}, time.Now())

	// Verify the args
	if args.DirEnt.Key == "" && args.Op != structs.KVSDeleteTree {
		return fmt.Errorf("Must provide key")
	}

	// Apply the ACL policy if any
	acl, err := k.srv.resolveToken(args.Token)
	if err != nil {
		return err
	} else if acl != nil {
		switch args.Op {
		case structs.KVSDeleteTree:
			if !acl.KeyWritePrefix(args.DirEnt.Key) {
				return permissionDeniedErr
			}
		default:
			if !acl.KeyWrite(args.DirEnt.Key) {
				return permissionDeniedErr
			}
		}
	}

	// If this is a lock, we must check for a lock-delay. Since lock-delay
	// is based on wall-time, each peer expire the lock-delay at a slightly
	// different time. This means the enforcement of lock-delay cannot be done
	// after the raft log is committed as it would lead to inconsistent FSMs.
	// Instead, the lock-delay must be enforced before commit. This means that
	// only the wall-time of the leader node is used, preventing any inconsistencies.
	if args.Op == structs.KVSLock {
		state := k.srv.fsm.State()
		expires := state.KVSLockDelay(args.DirEnt.Key)
		if expires.After(time.Now()) {
			k.srv.logger.Printf("[WARN] consul.kvs: Rejecting lock of %s due to lock-delay until %v",
				args.DirEnt.Key, expires)
			*reply = false
			return nil
		}
	}

	// Apply the update
	resp, err := k.srv.raftApply(structs.KVSRequestType, args)
	if err != nil {
		k.srv.logger.Printf("[ERR] consul.kvs: Apply failed: %v", err)
		return err
	}
	if respErr, ok := resp.(error); ok {
		return respErr
	}

	// Check if the return type is a bool
	if respBool, ok := resp.(bool); ok {
		*reply = respBool
	}
	return nil
}

// Get is used to lookup a single key
func (k *KVS) Get(args *structs.KeyRequest, reply *structs.IndexedDirEntries) error {
	if done, err := k.srv.forward("KVS.Get", args, args, reply); done {
		return err
	}

	acl, err := k.srv.resolveToken(args.Token)
	if err != nil {
		return err
	}

	// Get the local state
	state := k.srv.fsm.State()
	return k.srv.blockingRPC(&args.QueryOptions,
		&reply.QueryMeta,
		state.QueryTables("KVSGet"),
		func() error {
			index, ent, err := state.KVSGet(args.Key)
			if err != nil {
				return err
			}
			if acl != nil && !acl.KeyRead(args.Key) {
				ent = nil
			}
			if ent == nil {
				// Must provide non-zero index to prevent blocking
				// Index 1 is impossible anyways (due to Raft internals)
				if index == 0 {
					reply.Index = 1
				} else {
					reply.Index = index
				}
				reply.Entries = nil
			} else {
				reply.Index = ent.ModifyIndex
				reply.Entries = structs.DirEntries{ent}
			}
			return nil
		})
}

// List is used to list all keys with a given prefix
func (k *KVS) List(args *structs.KeyRequest, reply *structs.IndexedDirEntries) error {
	if done, err := k.srv.forward("KVS.List", args, args, reply); done {
		return err
	}

	acl, err := k.srv.resolveToken(args.Token)
	if err != nil {
		return err
	}

	// Get the local state
	state := k.srv.fsm.State()
	return k.srv.blockingRPC(&args.QueryOptions,
		&reply.QueryMeta,
		state.QueryTables("KVSList"),
		func() error {
			tombIndex, index, ent, err := state.KVSList(args.Key)
			if err != nil {
				return err
			}
			if acl != nil {
				ent = FilterDirEnt(acl, ent)
			}

			if len(ent) == 0 {
				// Must provide non-zero index to prevent blocking
				// Index 1 is impossible anyways (due to Raft internals)
				if index == 0 {
					reply.Index = 1
				} else {
					reply.Index = index
				}
			} else {
				// Determine the maximum affected index
				var maxIndex uint64
				for _, e := range ent {
					if e.ModifyIndex > maxIndex {
						maxIndex = e.ModifyIndex
					}
				}
				if tombIndex > maxIndex {
					maxIndex = tombIndex
				}
				reply.Index = maxIndex
				reply.Entries = ent
			}
			return nil
		})
}

// ListKeys is used to list all keys with a given prefix to a seperator
func (k *KVS) ListKeys(args *structs.KeyListRequest, reply *structs.IndexedKeyList) error {
	if done, err := k.srv.forward("KVS.ListKeys", args, args, reply); done {
		return err
	}

	acl, err := k.srv.resolveToken(args.Token)
	if err != nil {
		return err
	}

	// Get the local state
	state := k.srv.fsm.State()
	return k.srv.blockingRPC(&args.QueryOptions,
		&reply.QueryMeta,
		state.QueryTables("KVSListKeys"),
		func() error {
			index, keys, err := state.KVSListKeys(args.Prefix, args.Seperator)
			reply.Index = index
			if acl != nil {
				keys = FilterKeys(acl, keys)
			}
			reply.Keys = keys
			return err
		})
}
<|endoftext|>


<commit_before>// Copyright 2014 Google 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 container contains a Google Container Engine client.
//
// For more information about the API,
// see https://cloud.google.com/container-engine/docs
package container // import "cloud.google.com/go/container"

import (
	"errors"
	"fmt"
	"time"

	"golang.org/x/net/context"
	raw "google.golang.org/api/container/v1"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
)

type Type string

const (
	TypeCreate = Type("createCluster")
	TypeDelete = Type("deleteCluster")
)

type Status string

const (
	StatusDone         = Status("done")
	StatusPending      = Status("pending")
	StatusRunning      = Status("running")
	StatusError        = Status("error")
	StatusProvisioning = Status("provisioning")
	StatusStopping     = Status("stopping")
)

const prodAddr = "https://container.googleapis.com/"
const userAgent = "gcloud-golang-container/20151008"

// Client is a Google Container Engine client, which may be used to manage
// clusters with a project.  It must be constructed via NewClient.
type Client struct {
	projectID string
	svc       *raw.Service
}

// NewClient creates a new Google Container Engine client.
func NewClient(ctx context.Context, projectID string, opts ...option.ClientOption) (*Client, error) {
	o := []option.ClientOption{
		option.WithEndpoint(prodAddr),
		option.WithScopes(raw.CloudPlatformScope),
		option.WithUserAgent(userAgent),
	}
	o = append(o, opts...)
	httpClient, endpoint, err := transport.NewHTTPClient(ctx, o...)
	if err != nil {
		return nil, fmt.Errorf("dialing: %v", err)
	}

	svc, err := raw.New(httpClient)
	if err != nil {
		return nil, fmt.Errorf("constructing container client: %v", err)
	}
	svc.BasePath = endpoint

	c := &Client{
		projectID: projectID,
		svc:       svc,
	}

	return c, nil
}

// Resource is a Google Container Engine cluster resource.
type Resource struct {
	// Name is the name of this cluster. The name must be unique
	// within this project and zone, and can be up to 40 characters.
	Name string

	// Description is the description of the cluster. Optional.
	Description string

	// Zone is the Google Compute Engine zone in which the cluster resides.
	Zone string

	// Status is the current status of the cluster. It could either be
	// StatusError, StatusProvisioning, StatusRunning or StatusStopping.
	Status Status

	// Num is the number of the nodes in this cluster resource.
	Num int64

	// APIVersion is the version of the Kubernetes master and kubelets running
	// in this cluster. Allowed value is 0.4.2, or leave blank to
	// pick up the latest stable release.
	APIVersion string

	// Endpoint is the IP address of this cluster's Kubernetes master.
	// The endpoint can be accessed at https://username:password@endpoint/.
	// See Username and Password fields for the username and password information.
	Endpoint string

	// Username is the username to use when accessing the Kubernetes master endpoint.
	Username string

	// Password is the password to use when accessing the Kubernetes master endpoint.
	Password string

	// ContainerIPv4CIDR is the IP addresses of the container pods in
	// this cluster, in CIDR notation (e.g. 1.2.3.4/29).
	ContainerIPv4CIDR string

	// ServicesIPv4CIDR is the IP addresses of the Kubernetes services in this
	// cluster, in CIDR notation (e.g. 1.2.3.4/29). Service addresses are
	// always in the 10.0.0.0/16 range.
	ServicesIPv4CIDR string

	// MachineType is a Google Compute Engine machine type (e.g. n1-standard-1).
	// If none set, the default type is used while creating a new cluster.
	MachineType string

	// This field is ignored. It was removed from the underlying container API in v1.
	SourceImage string

	// Created is the creation time of this cluster.
	Created time.Time
}

func resourceFromRaw(c *raw.Cluster) *Resource {
	if c == nil {
		return nil
	}
	r := &Resource{
		Name:              c.Name,
		Description:       c.Description,
		Zone:              c.Zone,
		Status:            Status(c.Status),
		Num:               c.InitialNodeCount,
		APIVersion:        c.InitialClusterVersion,
		Endpoint:          c.Endpoint,
		Username:          c.MasterAuth.Username,
		Password:          c.MasterAuth.Password,
		ContainerIPv4CIDR: c.ClusterIpv4Cidr,
		ServicesIPv4CIDR:  c.ServicesIpv4Cidr,
		MachineType:       c.NodeConfig.MachineType,
	}
	r.Created, _ = time.Parse(time.RFC3339, c.CreateTime)
	return r
}

func resourcesFromRaw(c []*raw.Cluster) []*Resource {
	r := make([]*Resource, len(c))
	for i, val := range c {
		r[i] = resourceFromRaw(val)
	}
	return r
}

// Op represents a Google Container Engine API operation.
type Op struct {
	// Name is the name of the operation.
	Name string

	// Zone is the Google Compute Engine zone.
	Zone string

	// This field is ignored. It was removed from the underlying container API in v1.
	TargetURL string

	// Type is the operation type. It could be either be TypeCreate or TypeDelete.
	Type Type

	// Status is the current status of this operation. It could be either
	// OpDone or OpPending.
	Status Status
}

func opFromRaw(o *raw.Operation) *Op {
	if o == nil {
		return nil
	}
	return &Op{
		Name:   o.Name,
		Zone:   o.Zone,
		Type:   Type(o.OperationType),
		Status: Status(o.Status),
	}
}

func opsFromRaw(o []*raw.Operation) []*Op {
	ops := make([]*Op, len(o))
	for i, val := range o {
		ops[i] = opFromRaw(val)
	}
	return ops
}

// Clusters returns a list of cluster resources from the specified zone.
// If no zone is specified, it returns all clusters under the user project.
func (c *Client) Clusters(ctx context.Context, zone string) ([]*Resource, error) {
	if zone == "" {
		resp, err := c.svc.Projects.Zones.Clusters.List(c.projectID, "-").Do()
		if err != nil {
			return nil, err
		}
		return resourcesFromRaw(resp.Clusters), nil
	}
	resp, err := c.svc.Projects.Zones.Clusters.List(c.projectID, zone).Do()
	if err != nil {
		return nil, err
	}
	return resourcesFromRaw(resp.Clusters), nil
}

// Cluster returns metadata about the specified cluster.
func (c *Client) Cluster(ctx context.Context, zone, name string) (*Resource, error) {
	resp, err := c.svc.Projects.Zones.Clusters.Get(c.projectID, zone, name).Do()
	if err != nil {
		return nil, err
	}
	return resourceFromRaw(resp), nil
}

// CreateCluster creates a new cluster with the provided metadata
// in the specified zone.
func (c *Client) CreateCluster(ctx context.Context, zone string, resource *Resource) (*Resource, error) {
	panic("not implemented")
}

// DeleteCluster deletes a cluster.
func (c *Client) DeleteCluster(ctx context.Context, zone, name string) error {
	_, err := c.svc.Projects.Zones.Clusters.Delete(c.projectID, zone, name).Do()
	return err
}

// Operations returns a list of operations from the specified zone.
// If no zone is specified, it looks up for all of the operations
// that are running under the user's project.
func (c *Client) Operations(ctx context.Context, zone string) ([]*Op, error) {
	if zone == "" {
		resp, err := c.svc.Projects.Zones.Operations.List(c.projectID, "-").Do()
		if err != nil {
			return nil, err
		}
		return opsFromRaw(resp.Operations), nil
	}
	resp, err := c.svc.Projects.Zones.Operations.List(c.projectID, zone).Do()
	if err != nil {
		return nil, err
	}
	return opsFromRaw(resp.Operations), nil
}

// Operation returns an operation.
func (c *Client) Operation(ctx context.Context, zone, name string) (*Op, error) {
	resp, err := c.svc.Projects.Zones.Operations.Get(c.projectID, zone, name).Do()
	if err != nil {
		return nil, err
	}
	if resp.StatusMessage != "" {
		return nil, errors.New(resp.StatusMessage)
	}
	return opFromRaw(resp), nil
}
<commit_msg>container: remove duplicate code<commit_after>// Copyright 2014 Google 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 container contains a Google Container Engine client.
//
// For more information about the API,
// see https://cloud.google.com/container-engine/docs
package container // import "cloud.google.com/go/container"

import (
	"errors"
	"fmt"
	"time"

	"golang.org/x/net/context"
	raw "google.golang.org/api/container/v1"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
)

type Type string

const (
	TypeCreate = Type("createCluster")
	TypeDelete = Type("deleteCluster")
)

type Status string

const (
	StatusDone         = Status("done")
	StatusPending      = Status("pending")
	StatusRunning      = Status("running")
	StatusError        = Status("error")
	StatusProvisioning = Status("provisioning")
	StatusStopping     = Status("stopping")
)

const prodAddr = "https://container.googleapis.com/"
const userAgent = "gcloud-golang-container/20151008"

// Client is a Google Container Engine client, which may be used to manage
// clusters with a project.  It must be constructed via NewClient.
type Client struct {
	projectID string
	svc       *raw.Service
}

// NewClient creates a new Google Container Engine client.
func NewClient(ctx context.Context, projectID string, opts ...option.ClientOption) (*Client, error) {
	o := []option.ClientOption{
		option.WithEndpoint(prodAddr),
		option.WithScopes(raw.CloudPlatformScope),
		option.WithUserAgent(userAgent),
	}
	o = append(o, opts...)
	httpClient, endpoint, err := transport.NewHTTPClient(ctx, o...)
	if err != nil {
		return nil, fmt.Errorf("dialing: %v", err)
	}

	svc, err := raw.New(httpClient)
	if err != nil {
		return nil, fmt.Errorf("constructing container client: %v", err)
	}
	svc.BasePath = endpoint

	c := &Client{
		projectID: projectID,
		svc:       svc,
	}

	return c, nil
}

// Resource is a Google Container Engine cluster resource.
type Resource struct {
	// Name is the name of this cluster. The name must be unique
	// within this project and zone, and can be up to 40 characters.
	Name string

	// Description is the description of the cluster. Optional.
	Description string

	// Zone is the Google Compute Engine zone in which the cluster resides.
	Zone string

	// Status is the current status of the cluster. It could either be
	// StatusError, StatusProvisioning, StatusRunning or StatusStopping.
	Status Status

	// Num is the number of the nodes in this cluster resource.
	Num int64

	// APIVersion is the version of the Kubernetes master and kubelets running
	// in this cluster. Allowed value is 0.4.2, or leave blank to
	// pick up the latest stable release.
	APIVersion string

	// Endpoint is the IP address of this cluster's Kubernetes master.
	// The endpoint can be accessed at https://username:password@endpoint/.
	// See Username and Password fields for the username and password information.
	Endpoint string

	// Username is the username to use when accessing the Kubernetes master endpoint.
	Username string

	// Password is the password to use when accessing the Kubernetes master endpoint.
	Password string

	// ContainerIPv4CIDR is the IP addresses of the container pods in
	// this cluster, in CIDR notation (e.g. 1.2.3.4/29).
	ContainerIPv4CIDR string

	// ServicesIPv4CIDR is the IP addresses of the Kubernetes services in this
	// cluster, in CIDR notation (e.g. 1.2.3.4/29). Service addresses are
	// always in the 10.0.0.0/16 range.
	ServicesIPv4CIDR string

	// MachineType is a Google Compute Engine machine type (e.g. n1-standard-1).
	// If none set, the default type is used while creating a new cluster.
	MachineType string

	// This field is ignored. It was removed from the underlying container API in v1.
	SourceImage string

	// Created is the creation time of this cluster.
	Created time.Time
}

func resourceFromRaw(c *raw.Cluster) *Resource {
	if c == nil {
		return nil
	}
	r := &Resource{
		Name:              c.Name,
		Description:       c.Description,
		Zone:              c.Zone,
		Status:            Status(c.Status),
		Num:               c.InitialNodeCount,
		APIVersion:        c.InitialClusterVersion,
		Endpoint:          c.Endpoint,
		Username:          c.MasterAuth.Username,
		Password:          c.MasterAuth.Password,
		ContainerIPv4CIDR: c.ClusterIpv4Cidr,
		ServicesIPv4CIDR:  c.ServicesIpv4Cidr,
		MachineType:       c.NodeConfig.MachineType,
	}
	r.Created, _ = time.Parse(time.RFC3339, c.CreateTime)
	return r
}

func resourcesFromRaw(c []*raw.Cluster) []*Resource {
	r := make([]*Resource, len(c))
	for i, val := range c {
		r[i] = resourceFromRaw(val)
	}
	return r
}

// Op represents a Google Container Engine API operation.
type Op struct {
	// Name is the name of the operation.
	Name string

	// Zone is the Google Compute Engine zone.
	Zone string

	// This field is ignored. It was removed from the underlying container API in v1.
	TargetURL string

	// Type is the operation type. It could be either be TypeCreate or TypeDelete.
	Type Type

	// Status is the current status of this operation. It could be either
	// OpDone or OpPending.
	Status Status
}

func opFromRaw(o *raw.Operation) *Op {
	if o == nil {
		return nil
	}
	return &Op{
		Name:   o.Name,
		Zone:   o.Zone,
		Type:   Type(o.OperationType),
		Status: Status(o.Status),
	}
}

func opsFromRaw(o []*raw.Operation) []*Op {
	ops := make([]*Op, len(o))
	for i, val := range o {
		ops[i] = opFromRaw(val)
	}
	return ops
}

// Clusters returns a list of cluster resources from the specified zone.
// If no zone is specified, it returns all clusters under the user project.
func (c *Client) Clusters(ctx context.Context, zone string) ([]*Resource, error) {
	if zone == "" {
		zone = "-"
	}
	resp, err := c.svc.Projects.Zones.Clusters.List(c.projectID, zone).Do()
	if err != nil {
		return nil, err
	}
	return resourcesFromRaw(resp.Clusters), nil
}

// Cluster returns metadata about the specified cluster.
func (c *Client) Cluster(ctx context.Context, zone, name string) (*Resource, error) {
	resp, err := c.svc.Projects.Zones.Clusters.Get(c.projectID, zone, name).Do()
	if err != nil {
		return nil, err
	}
	return resourceFromRaw(resp), nil
}

// CreateCluster creates a new cluster with the provided metadata
// in the specified zone.
func (c *Client) CreateCluster(ctx context.Context, zone string, resource *Resource) (*Resource, error) {
	panic("not implemented")
}

// DeleteCluster deletes a cluster.
func (c *Client) DeleteCluster(ctx context.Context, zone, name string) error {
	_, err := c.svc.Projects.Zones.Clusters.Delete(c.projectID, zone, name).Do()
	return err
}

// Operations returns a list of operations from the specified zone.
// If no zone is specified, it looks up for all of the operations
// that are running under the user's project.
func (c *Client) Operations(ctx context.Context, zone string) ([]*Op, error) {
	if zone == "" {
		resp, err := c.svc.Projects.Zones.Operations.List(c.projectID, "-").Do()
		if err != nil {
			return nil, err
		}
		return opsFromRaw(resp.Operations), nil
	}
	resp, err := c.svc.Projects.Zones.Operations.List(c.projectID, zone).Do()
	if err != nil {
		return nil, err
	}
	return opsFromRaw(resp.Operations), nil
}

// Operation returns an operation.
func (c *Client) Operation(ctx context.Context, zone, name string) (*Op, error) {
	resp, err := c.svc.Projects.Zones.Operations.Get(c.projectID, zone, name).Do()
	if err != nil {
		return nil, err
	}
	if resp.StatusMessage != "" {
		return nil, errors.New(resp.StatusMessage)
	}
	return opFromRaw(resp), nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"io"
	"log"
	"net/url"
	"path"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

type Link struct {
	NodeName string
	Text     string
	URL      string
}

func NormalizeString(s string) string {
	return strings.Join(strings.Fields(s), " ")
}

func ImageText(s *goquery.Selection) string {
	alt, _ := s.Attr("alt")
	if alt != "" {
		return alt
	}

	title, _ := s.Attr("title")
	if title != "" {
		return title
	}

	src, ok := s.Attr("src")
	if !ok {
		return "NO TEXT"
	}

	if src == "" {
		return "NO TEXT"
	}

	imageURL, err := url.Parse(src)
	if err != nil {
		log.Fatal(err)
	}

	return path.Base(imageURL.Path)
}

func FindLinks(file io.Reader) ([]Link, error) {
	doc, err := goquery.NewDocumentFromReader(file)
	if err != nil {
		return nil, err
	}

	var links []Link
	doc.Find("a").Each(func(i int, s *goquery.Selection) {
		url, ok := s.Attr("href")
		if !ok {
			return
		}

		node := goquery.NodeName(s)
		text := NormalizeString(s.Text())

		s.Children().Each(func(i int, s *goquery.Selection) {
			node = goquery.NodeName(s)
			if node == "img" {
				text = ImageText(s)
				return
			}
		})

		if text == "" {
			text = "NO TEXT"
		}

		links = append(links, Link{node, text, url})
	})

	if len(links) == 0 {
		return nil, errors.New("no links found")
	}

	return links, nil
}
<commit_msg>Condense empty src check<commit_after>package main

import (
	"errors"
	"io"
	"log"
	"net/url"
	"path"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

type Link struct {
	NodeName string
	Text     string
	URL      string
}

func NormalizeString(s string) string {
	return strings.Join(strings.Fields(s), " ")
}

func ImageText(s *goquery.Selection) string {
	alt, _ := s.Attr("alt")
	if alt != "" {
		return alt
	}

	title, _ := s.Attr("title")
	if title != "" {
		return title
	}

	src, ok := s.Attr("src")
	if !ok || src == "" {
		return "NO TEXT"
	}

	imageURL, err := url.Parse(src)
	if err != nil {
		log.Fatal(err)
	}

	return path.Base(imageURL.Path)
}

func FindLinks(file io.Reader) ([]Link, error) {
	doc, err := goquery.NewDocumentFromReader(file)
	if err != nil {
		return nil, err
	}

	var links []Link
	doc.Find("a").Each(func(i int, s *goquery.Selection) {
		url, ok := s.Attr("href")
		if !ok {
			return
		}

		node := goquery.NodeName(s)
		text := NormalizeString(s.Text())

		s.Children().Each(func(i int, s *goquery.Selection) {
			node = goquery.NodeName(s)
			if node == "img" {
				text = ImageText(s)
				return
			}
		})

		if text == "" {
			text = "NO TEXT"
		}

		links = append(links, Link{node, text, url})
	})

	if len(links) == 0 {
		return nil, errors.New("no links found")
	}

	return links, nil
}
<|endoftext|>


<commit_before>package toolbox

import (
	"fmt"
	"reflect"
	"strings"
)

//GetFunction returns function for provided owner and name, or error
func GetFunction(owner interface{}, name string) (interface{}, error) {
	if owner == nil {
		return nil, fmt.Errorf("failed to lookup %v on %T, owner was nil", name, owner)
	}
	var ownerType = reflect.TypeOf(owner)
	var method, has = ownerType.MethodByName(name)
	if !has {
		var available = make([]string, 0)
		for i := 0; i < ownerType.NumMethod(); i++ {
			available = append(available, ownerType.Method(i).Name)
		}
		return nil, fmt.Errorf("failed to lookup %T.%v, available:[%v]", owner, name, strings.Join(available, ","))
	}
	return reflect.ValueOf(owner).MethodByName(method.Name).Interface(), nil
}

//CallFunction calls passed in function with provided parameters,it returns a function result.
func CallFunction(function interface{}, parameters ...interface{}) []interface{} {
	AssertKind(function, reflect.Func, "function")
	var functionParameters = make([]reflect.Value, 0)
	ProcessSlice(parameters, func(item interface{}) bool {
		functionParameters = append(functionParameters, reflect.ValueOf(item))
		return true
	})

	functionValue := reflect.ValueOf(function)
	var resultValues = functionValue.Call(functionParameters)
	var result = make([]interface{}, len(resultValues))
	for i, resultValue := range resultValues {
		result[i] = resultValue.Interface()
	}
	return result
}

//AsCompatibleFunctionParameters takes incompatible function parameters and converts then into provided function signature compatible
func AsCompatibleFunctionParameters(function interface{}, parameters []interface{}) ([]interface{}, error) {
	AssertKind(function, reflect.Func, "function")
	functionValue := reflect.ValueOf(function)
	funcSignature := GetFuncSignature(function)
	actualMethodSignatureLength := len(funcSignature)
	converter := Converter{}
	if actualMethodSignatureLength != len(parameters) {
		return nil, fmt.Errorf("invalid number of parameters wanted: [%T],  had: %v", function, 0)
	}
	var functionParameters = make([]interface{}, 0)
	for i, parameterValue := range parameters {

		if parameterValue == nil {
			return nil, fmt.Errorf("parameter[%v] was empty", i)
		}

		reflectValue := reflect.ValueOf(parameterValue)
		if reflectValue.Kind() == reflect.Slice && funcSignature[i].Kind() != reflectValue.Kind() {
			return nil, fmt.Errorf("incompatible types expected: %v, but had %v", funcSignature[i].Kind(), reflectValue.Kind())
		} else if !reflectValue.IsValid() {
			if funcSignature[i].Kind() == reflect.Slice {
				parameterValue = reflect.New(funcSignature[i]).Interface()
				reflectValue = reflect.ValueOf(parameterValue)
			}
		}

		if reflectValue.Type() != funcSignature[i] {
			newValuePointer := reflect.New(funcSignature[i])
			err := converter.AssignConverted(newValuePointer.Interface(), parameterValue)
			if err != nil {
				return nil, fmt.Errorf("failed to assign convert %v to %v due to %v", parameterValue, newValuePointer.Interface(), err)
			}
			reflectValue = newValuePointer.Elem()
		}
		if functionValue.Type().IsVariadic() && funcSignature[i].Kind() == reflect.Slice && i+1 == len(funcSignature) {
			ProcessSlice(reflectValue.Interface(), func(item interface{}) bool {
				functionParameters = append(functionParameters, item)
				return true
			})
		} else {
			functionParameters = append(functionParameters, reflectValue.Interface())
		}
	}
	return functionParameters, nil
}

//BuildFunctionParameters builds function parameters provided in the parameterValues.
// Parameters value will be converted if needed to expected by the function signature type. It returns function parameters , or error
func BuildFunctionParameters(function interface{}, parameters []string, parameterValues map[string]interface{}) ([]interface{}, error) {
	var functionParameters = make([]interface{}, 0)
	for _, name := range parameters {
		functionParameters = append(functionParameters, parameterValues[name])
	}
	return AsCompatibleFunctionParameters(function, functionParameters)
}

//GetFuncSignature returns a function signature
func GetFuncSignature(function interface{}) []reflect.Type {
	AssertKind(function, reflect.Func, "function")
	functionValue := reflect.ValueOf(function)
	var result = make([]reflect.Type, 0)
	functionType := functionValue.Type()
	for i := 0; i < functionType.NumIn(); i++ {
		result = append(result, functionType.In(i))
	}
	return result
}
<commit_msg>patched arg count reporting<commit_after>package toolbox

import (
	"fmt"
	"reflect"
	"strings"
)

//GetFunction returns function for provided owner and name, or error
func GetFunction(owner interface{}, name string) (interface{}, error) {
	if owner == nil {
		return nil, fmt.Errorf("failed to lookup %v on %T, owner was nil", name, owner)
	}
	var ownerType = reflect.TypeOf(owner)
	var method, has = ownerType.MethodByName(name)
	if !has {
		var available = make([]string, 0)
		for i := 0; i < ownerType.NumMethod(); i++ {
			available = append(available, ownerType.Method(i).Name)
		}
		return nil, fmt.Errorf("failed to lookup %T.%v, available:[%v]", owner, name, strings.Join(available, ","))
	}
	return reflect.ValueOf(owner).MethodByName(method.Name).Interface(), nil
}

//CallFunction calls passed in function with provided parameters,it returns a function result.
func CallFunction(function interface{}, parameters ...interface{}) []interface{} {
	AssertKind(function, reflect.Func, "function")
	var functionParameters = make([]reflect.Value, 0)
	ProcessSlice(parameters, func(item interface{}) bool {
		functionParameters = append(functionParameters, reflect.ValueOf(item))
		return true
	})

	functionValue := reflect.ValueOf(function)
	var resultValues = functionValue.Call(functionParameters)
	var result = make([]interface{}, len(resultValues))
	for i, resultValue := range resultValues {
		result[i] = resultValue.Interface()
	}
	return result
}

//AsCompatibleFunctionParameters takes incompatible function parameters and converts then into provided function signature compatible
func AsCompatibleFunctionParameters(function interface{}, parameters []interface{}) ([]interface{}, error) {
	AssertKind(function, reflect.Func, "function")
	functionValue := reflect.ValueOf(function)
	funcSignature := GetFuncSignature(function)
	actualMethodSignatureLength := len(funcSignature)
	converter := Converter{}
	if actualMethodSignatureLength != len(parameters) {
		return nil, fmt.Errorf("invalid number of parameters wanted: [%T],  had: %v", function, len(parameters))
	}
	var functionParameters = make([]interface{}, 0)
	for i, parameterValue := range parameters {

		if parameterValue == nil {
			return nil, fmt.Errorf("parameter[%v] was empty", i)
		}

		reflectValue := reflect.ValueOf(parameterValue)
		if reflectValue.Kind() == reflect.Slice && funcSignature[i].Kind() != reflectValue.Kind() {
			return nil, fmt.Errorf("incompatible types expected: %v, but had %v", funcSignature[i].Kind(), reflectValue.Kind())
		} else if !reflectValue.IsValid() {
			if funcSignature[i].Kind() == reflect.Slice {
				parameterValue = reflect.New(funcSignature[i]).Interface()
				reflectValue = reflect.ValueOf(parameterValue)
			}
		}

		if reflectValue.Type() != funcSignature[i] {
			newValuePointer := reflect.New(funcSignature[i])
			err := converter.AssignConverted(newValuePointer.Interface(), parameterValue)
			if err != nil {
				return nil, fmt.Errorf("failed to assign convert %v to %v due to %v", parameterValue, newValuePointer.Interface(), err)
			}
			reflectValue = newValuePointer.Elem()
		}
		if functionValue.Type().IsVariadic() && funcSignature[i].Kind() == reflect.Slice && i+1 == len(funcSignature) {
			ProcessSlice(reflectValue.Interface(), func(item interface{}) bool {
				functionParameters = append(functionParameters, item)
				return true
			})
		} else {
			functionParameters = append(functionParameters, reflectValue.Interface())
		}
	}
	return functionParameters, nil
}

//BuildFunctionParameters builds function parameters provided in the parameterValues.
// Parameters value will be converted if needed to expected by the function signature type. It returns function parameters , or error
func BuildFunctionParameters(function interface{}, parameters []string, parameterValues map[string]interface{}) ([]interface{}, error) {
	var functionParameters = make([]interface{}, 0)
	for _, name := range parameters {
		functionParameters = append(functionParameters, parameterValues[name])
	}
	return AsCompatibleFunctionParameters(function, functionParameters)
}

//GetFuncSignature returns a function signature
func GetFuncSignature(function interface{}) []reflect.Type {
	AssertKind(function, reflect.Func, "function")
	functionValue := reflect.ValueOf(function)
	var result = make([]reflect.Type, 0)
	functionType := functionValue.Type()
	for i := 0; i < functionType.NumIn(); i++ {
		result = append(result, functionType.In(i))
	}
	return result
}
<|endoftext|>


<commit_before>package fusefs

import (
	"errors"
	"sync"
)

// inodeMap provides a mapping from fuse.Node to and from the Path that it
// corresponds to.
type inodeMap struct {
	inodes    map[uint64]string
	lastInode uint64
	sync.RWMutex
}

func NewInodeMap() inodeMap {
	return inodeMap{
		inodes: map[uint64]string{
			1: "/",
		},
		lastInode: 1,
	}
}

func (im *inodeMap) ToPath(inode uint64) (string, error) {
	im.RLock()
	defer im.RUnlock()
	if p, ok := im.inodes[inode]; ok {
		return p, nil
	}
	return "", errors.New("inode not allocated")
}

func (im *inodeMap) FromPath(p string) uint64 {
	im.RLock()
	for inode, path := range im.inodes {
		if p == path {
			return inode
		}
	}
	im.RUnlock()

	// allocate the inode
	im.Lock()
	defer im.Unlock()
	im.lastInode++
	im.inodes[im.lastInode] = p
	return im.lastInode
}

func (im *inodeMap) Release(inode uint64) {
	im.Lock()
	delete(im.inodes, inode)
	im.Unlock()
}
<commit_msg>deferred an unlock<commit_after>package fusefs

import (
	"errors"
	"sync"
)

// inodeMap provides a mapping from fuse.Node to and from the Path that it
// corresponds to.
type inodeMap struct {
	inodes    map[uint64]string
	lastInode uint64
	sync.RWMutex
}

func NewInodeMap() inodeMap {
	return inodeMap{
		inodes: map[uint64]string{
			1: "/",
		},
		lastInode: 1,
	}
}

func (im *inodeMap) ToPath(inode uint64) (string, error) {
	im.RLock()
	defer im.RUnlock()
	if p, ok := im.inodes[inode]; ok {
		return p, nil
	}
	return "", errors.New("inode not allocated")
}

func (im *inodeMap) FromPath(p string) uint64 {
	im.RLock()
	for inode, path := range im.inodes {
		if p == path {
			return inode
		}
	}
	im.RUnlock()

	// allocate the inode
	im.Lock()
	defer im.Unlock()
	im.lastInode++
	im.inodes[im.lastInode] = p
	return im.lastInode
}

func (im *inodeMap) Release(inode uint64) {
	im.Lock()
	defer im.Unlock()
	delete(im.inodes, inode)
}
<|endoftext|>


<commit_before>package logfmt_test

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"testing"

	"github.com/go-logfmt/logfmt"
)

func TestEncodeKeyval(t *testing.T) {
	data := []struct {
		key, value interface{}
		want       string
		err        error
	}{
		{key: "k", value: "v", want: "k=v"},
		{key: "k", value: nil, want: "k=null"},
		{key: `\`, value: "v", want: `\=v`},
		{key: "k", value: "", want: "k="},
		{key: "k", value: "null", want: `k="null"`},
		{key: "k", value: "<nil>", want: `k=<nil>`},
		{key: "k", value: true, want: "k=true"},
		{key: "k", value: 1, want: "k=1"},
		{key: "k", value: 1.025, want: "k=1.025"},
		{key: "k", value: 1e-3, want: "k=0.001"},
		{key: "k", value: 3.5 + 2i, want: "k=(3.5+2i)"},
		{key: "k", value: "v v", want: `k="v v"`},
		{key: "k", value: " ", want: `k=" "`},
		{key: "k", value: `"`, want: `k="\""`},
		{key: "k", value: `=`, want: `k="="`},
		{key: "k", value: `\`, want: `k=\`},
		{key: "k", value: `=\`, want: `k="=\\"`},
		{key: "k", value: `\"`, want: `k="\\\""`},
		{key: "k", value: [2]int{2, 19}, err: logfmt.ErrUnsupportedValueType},
		{key: "k", value: []string{"e1", "e 2"}, err: logfmt.ErrUnsupportedValueType},
		{key: "k", value: structData{"a a", 9}, err: logfmt.ErrUnsupportedValueType},
		{key: "k", value: decimalMarshaler{5, 9}, want: "k=5.9"},
		{key: "k", value: (*decimalMarshaler)(nil), want: "k=null"},
		{key: "k", value: decimalStringer{5, 9}, want: "k=5.9"},
		{key: "k", value: (*decimalStringer)(nil), want: "k=null"},
		{key: "k", value: marshalerStringer{5, 9}, want: "k=5.9"},
		{key: "k", value: (*marshalerStringer)(nil), want: "k=null"},
		{key: "k", value: new(nilMarshaler), want: "k=notnilmarshaler"},
		{key: "k", value: (*nilMarshaler)(nil), want: "k=nilmarshaler"},
		{key: (*marshalerStringer)(nil), value: "v", err: logfmt.ErrNilKey},
		{key: decimalMarshaler{5, 9}, value: "v", want: "5.9=v"},
		{key: (*decimalMarshaler)(nil), value: "v", err: logfmt.ErrNilKey},
		{key: decimalStringer{5, 9}, value: "v", want: "5.9=v"},
		{key: (*decimalStringer)(nil), value: "v", err: logfmt.ErrNilKey},
		{key: marshalerStringer{5, 9}, value: "v", want: "5.9=v"},
	}

	for _, d := range data {
		w := &bytes.Buffer{}
		enc := logfmt.NewEncoder(w)
		err := enc.EncodeKeyval(d.key, d.value)
		if err != d.err {
			t.Errorf("%#v, %#v: got error: %v, want error: %v", d.key, d.value, err, d.err)
		}
		if got, want := w.String(), d.want; got != want {
			t.Errorf("%#v, %#v: got '%s', want '%s'", d.key, d.value, got, want)
		}
	}
}

func TestMarshalKeyvals(t *testing.T) {
	one := 1
	ptr := &one
	nilPtr := (*int)(nil)

	data := []struct {
		in   []interface{}
		want []byte
		err  error
	}{
		{in: nil, want: nil},
		{in: kv(), want: nil},
		{in: kv(nil, "v"), err: logfmt.ErrNilKey},
		{in: kv(nilPtr, "v"), err: logfmt.ErrNilKey},
		{in: kv("k"), want: []byte("k=null")},
		{in: kv("k", nil), want: []byte("k=null")},
		{in: kv("k", ""), want: []byte("k=")},
		{in: kv("k", "null"), want: []byte(`k="null"`)},
		{in: kv("k", "v"), want: []byte("k=v")},
		{in: kv("k", true), want: []byte("k=true")},
		{in: kv("k", 1), want: []byte("k=1")},
		{in: kv("k", ptr), want: []byte("k=1")},
		{in: kv("k", nilPtr), want: []byte("k=null")},
		{in: kv("k", 1.025), want: []byte("k=1.025")},
		{in: kv("k", 1e-3), want: []byte("k=0.001")},
		{in: kv("k", "v v"), want: []byte(`k="v v"`)},
		{in: kv("k", `"`), want: []byte(`k="\""`)},
		{in: kv("k", `=`), want: []byte(`k="="`)},
		{in: kv("k", `\`), want: []byte(`k=\`)},
		{in: kv("k", `=\`), want: []byte(`k="=\\"`)},
		{in: kv("k", `\"`), want: []byte(`k="\\\""`)},
		{in: kv("k1", "v1", "k2", "v2"), want: []byte("k1=v1 k2=v2")},
		{in: kv("k1", "v1", "k2", [2]int{}), want: []byte("k1=v1 k2=\"unsupported value type\"")},
		{in: kv([2]int{}, "v1", "k2", "v2"), want: []byte("k2=v2")},
		{in: kv("k", errorMarshaler{}), want: []byte("k=\"error marshaling value of type logfmt_test.errorMarshaler: marshal error\"")},
		{in: kv("k", decimalMarshaler{5, 9}), want: []byte("k=5.9")},
		{in: kv("k", (*decimalMarshaler)(nil)), want: []byte("k=null")},
		{in: kv("k", decimalStringer{5, 9}), want: []byte("k=5.9")},
		{in: kv("k", (*decimalStringer)(nil)), want: []byte("k=null")},
		{in: kv("k", marshalerStringer{5, 9}), want: []byte("k=5.9")},
		{in: kv("k", (*marshalerStringer)(nil)), want: []byte("k=null")},
		{in: kv(one, "v"), want: []byte("1=v")},
		{in: kv(ptr, "v"), want: []byte("1=v")},
		{in: kv((*marshalerStringer)(nil), "v"), err: logfmt.ErrNilKey},
		{in: kv(decimalMarshaler{5, 9}, "v"), want: []byte("5.9=v")},
		{in: kv((*decimalMarshaler)(nil), "v"), err: logfmt.ErrNilKey},
		{in: kv(decimalStringer{5, 9}, "v"), want: []byte("5.9=v")},
		{in: kv((*decimalStringer)(nil), "v"), err: logfmt.ErrNilKey},
		{in: kv(marshalerStringer{5, 9}, "v"), want: []byte("5.9=v")},
	}

	for _, d := range data {
		got, err := logfmt.MarshalKeyvals(d.in...)
		if err != d.err {
			t.Errorf("%#v: got error: %v, want error: %v", d.in, err, d.err)
		}
		if got, want := got, d.want; !reflect.DeepEqual(got, want) {
			t.Errorf("%#v: got '%s', want '%s'", d.in, got, want)
		}
	}
}

func kv(keyvals ...interface{}) []interface{} {
	return keyvals
}

type structData struct {
	A string `logfmt:"fieldA"`
	B int
}

type nilMarshaler int

func (m *nilMarshaler) MarshalText() ([]byte, error) {
	if m == nil {
		return []byte("nilmarshaler"), nil
	}
	return []byte("notnilmarshaler"), nil
}

type decimalMarshaler struct {
	a, b int
}

func (t decimalMarshaler) MarshalText() ([]byte, error) {
	buf := &bytes.Buffer{}
	fmt.Fprintf(buf, "%d.%d", t.a, t.b)
	return buf.Bytes(), nil
}

type decimalStringer struct {
	a, b int
}

func (s decimalStringer) String() string {
	return fmt.Sprintf("%d.%d", s.a, s.b)
}

type marshalerStringer struct {
	a, b int
}

func (t marshalerStringer) MarshalText() ([]byte, error) {
	buf := &bytes.Buffer{}
	fmt.Fprintf(buf, "%d.%d", t.a, t.b)
	return buf.Bytes(), nil
}

func (t marshalerStringer) String() string {
	return fmt.Sprint(t.a + t.b)
}

var marshalError = errors.New("marshal error")

type errorMarshaler struct{}

func (errorMarshaler) MarshalText() ([]byte, error) {
	return nil, marshalError
}
<commit_msg>Add test for time.Time values.<commit_after>package logfmt_test

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"testing"
	"time"

	"github.com/go-logfmt/logfmt"
)

func TestEncodeKeyval(t *testing.T) {
	data := []struct {
		key, value interface{}
		want       string
		err        error
	}{
		{key: "k", value: "v", want: "k=v"},
		{key: "k", value: nil, want: "k=null"},
		{key: `\`, value: "v", want: `\=v`},
		{key: "k", value: "", want: "k="},
		{key: "k", value: "null", want: `k="null"`},
		{key: "k", value: "<nil>", want: `k=<nil>`},
		{key: "k", value: true, want: "k=true"},
		{key: "k", value: 1, want: "k=1"},
		{key: "k", value: 1.025, want: "k=1.025"},
		{key: "k", value: 1e-3, want: "k=0.001"},
		{key: "k", value: 3.5 + 2i, want: "k=(3.5+2i)"},
		{key: "k", value: "v v", want: `k="v v"`},
		{key: "k", value: " ", want: `k=" "`},
		{key: "k", value: `"`, want: `k="\""`},
		{key: "k", value: `=`, want: `k="="`},
		{key: "k", value: `\`, want: `k=\`},
		{key: "k", value: `=\`, want: `k="=\\"`},
		{key: "k", value: `\"`, want: `k="\\\""`},
		{key: "k", value: [2]int{2, 19}, err: logfmt.ErrUnsupportedValueType},
		{key: "k", value: []string{"e1", "e 2"}, err: logfmt.ErrUnsupportedValueType},
		{key: "k", value: structData{"a a", 9}, err: logfmt.ErrUnsupportedValueType},
		{key: "k", value: decimalMarshaler{5, 9}, want: "k=5.9"},
		{key: "k", value: (*decimalMarshaler)(nil), want: "k=null"},
		{key: "k", value: decimalStringer{5, 9}, want: "k=5.9"},
		{key: "k", value: (*decimalStringer)(nil), want: "k=null"},
		{key: "k", value: marshalerStringer{5, 9}, want: "k=5.9"},
		{key: "k", value: (*marshalerStringer)(nil), want: "k=null"},
		{key: "k", value: new(nilMarshaler), want: "k=notnilmarshaler"},
		{key: "k", value: (*nilMarshaler)(nil), want: "k=nilmarshaler"},
		{key: (*marshalerStringer)(nil), value: "v", err: logfmt.ErrNilKey},
		{key: decimalMarshaler{5, 9}, value: "v", want: "5.9=v"},
		{key: (*decimalMarshaler)(nil), value: "v", err: logfmt.ErrNilKey},
		{key: decimalStringer{5, 9}, value: "v", want: "5.9=v"},
		{key: (*decimalStringer)(nil), value: "v", err: logfmt.ErrNilKey},
		{key: marshalerStringer{5, 9}, value: "v", want: "5.9=v"},
	}

	for _, d := range data {
		w := &bytes.Buffer{}
		enc := logfmt.NewEncoder(w)
		err := enc.EncodeKeyval(d.key, d.value)
		if err != d.err {
			t.Errorf("%#v, %#v: got error: %v, want error: %v", d.key, d.value, err, d.err)
		}
		if got, want := w.String(), d.want; got != want {
			t.Errorf("%#v, %#v: got '%s', want '%s'", d.key, d.value, got, want)
		}
	}
}

func TestMarshalKeyvals(t *testing.T) {
	one := 1
	ptr := &one
	nilPtr := (*int)(nil)

	data := []struct {
		in   []interface{}
		want []byte
		err  error
	}{
		{in: nil, want: nil},
		{in: kv(), want: nil},
		{in: kv(nil, "v"), err: logfmt.ErrNilKey},
		{in: kv(nilPtr, "v"), err: logfmt.ErrNilKey},
		{in: kv("k"), want: []byte("k=null")},
		{in: kv("k", nil), want: []byte("k=null")},
		{in: kv("k", ""), want: []byte("k=")},
		{in: kv("k", "null"), want: []byte(`k="null"`)},
		{in: kv("k", "v"), want: []byte("k=v")},
		{in: kv("k", true), want: []byte("k=true")},
		{in: kv("k", 1), want: []byte("k=1")},
		{in: kv("k", ptr), want: []byte("k=1")},
		{in: kv("k", nilPtr), want: []byte("k=null")},
		{in: kv("k", 1.025), want: []byte("k=1.025")},
		{in: kv("k", 1e-3), want: []byte("k=0.001")},
		{in: kv("k", "v v"), want: []byte(`k="v v"`)},
		{in: kv("k", `"`), want: []byte(`k="\""`)},
		{in: kv("k", `=`), want: []byte(`k="="`)},
		{in: kv("k", `\`), want: []byte(`k=\`)},
		{in: kv("k", `=\`), want: []byte(`k="=\\"`)},
		{in: kv("k", `\"`), want: []byte(`k="\\\""`)},
		{in: kv("k1", "v1", "k2", "v2"), want: []byte("k1=v1 k2=v2")},
		{in: kv("k1", "v1", "k2", [2]int{}), want: []byte("k1=v1 k2=\"unsupported value type\"")},
		{in: kv([2]int{}, "v1", "k2", "v2"), want: []byte("k2=v2")},
		{in: kv("k", time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)), want: []byte("k=2009-11-10T23:00:00Z")},
		{in: kv("k", errorMarshaler{}), want: []byte("k=\"error marshaling value of type logfmt_test.errorMarshaler: marshal error\"")},
		{in: kv("k", decimalMarshaler{5, 9}), want: []byte("k=5.9")},
		{in: kv("k", (*decimalMarshaler)(nil)), want: []byte("k=null")},
		{in: kv("k", decimalStringer{5, 9}), want: []byte("k=5.9")},
		{in: kv("k", (*decimalStringer)(nil)), want: []byte("k=null")},
		{in: kv("k", marshalerStringer{5, 9}), want: []byte("k=5.9")},
		{in: kv("k", (*marshalerStringer)(nil)), want: []byte("k=null")},
		{in: kv(one, "v"), want: []byte("1=v")},
		{in: kv(ptr, "v"), want: []byte("1=v")},
		{in: kv((*marshalerStringer)(nil), "v"), err: logfmt.ErrNilKey},
		{in: kv(decimalMarshaler{5, 9}, "v"), want: []byte("5.9=v")},
		{in: kv((*decimalMarshaler)(nil), "v"), err: logfmt.ErrNilKey},
		{in: kv(decimalStringer{5, 9}, "v"), want: []byte("5.9=v")},
		{in: kv((*decimalStringer)(nil), "v"), err: logfmt.ErrNilKey},
		{in: kv(marshalerStringer{5, 9}, "v"), want: []byte("5.9=v")},
	}

	for _, d := range data {
		got, err := logfmt.MarshalKeyvals(d.in...)
		if err != d.err {
			t.Errorf("%#v: got error: %v, want error: %v", d.in, err, d.err)
		}
		if got, want := got, d.want; !reflect.DeepEqual(got, want) {
			t.Errorf("%#v: got '%s', want '%s'", d.in, got, want)
		}
	}
}

func kv(keyvals ...interface{}) []interface{} {
	return keyvals
}

type structData struct {
	A string `logfmt:"fieldA"`
	B int
}

type nilMarshaler int

func (m *nilMarshaler) MarshalText() ([]byte, error) {
	if m == nil {
		return []byte("nilmarshaler"), nil
	}
	return []byte("notnilmarshaler"), nil
}

type decimalMarshaler struct {
	a, b int
}

func (t decimalMarshaler) MarshalText() ([]byte, error) {
	buf := &bytes.Buffer{}
	fmt.Fprintf(buf, "%d.%d", t.a, t.b)
	return buf.Bytes(), nil
}

type decimalStringer struct {
	a, b int
}

func (s decimalStringer) String() string {
	return fmt.Sprintf("%d.%d", s.a, s.b)
}

type marshalerStringer struct {
	a, b int
}

func (t marshalerStringer) MarshalText() ([]byte, error) {
	buf := &bytes.Buffer{}
	fmt.Fprintf(buf, "%d.%d", t.a, t.b)
	return buf.Bytes(), nil
}

func (t marshalerStringer) String() string {
	return fmt.Sprint(t.a + t.b)
}

var marshalError = errors.New("marshal error")

type errorMarshaler struct{}

func (errorMarshaler) MarshalText() ([]byte, error) {
	return nil, marshalError
}
<|endoftext|>