<commit_before>/*
Copyright 2014 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 aws

import (
	"fmt"
	"strconv"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/golang/glog"
	"k8s.io/kubernetes/pkg/types"
	"k8s.io/kubernetes/pkg/util/sets"
)

const ProxyProtocolPolicyName = "k8s-proxyprotocol-enabled"

func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBalancerName string, listeners []*elb.Listener, subnetIDs []string, securityGroupIDs []string, internalELB, proxyProtocol bool) (*elb.LoadBalancerDescription, error) {
	loadBalancer, err := c.describeLoadBalancer(loadBalancerName)
	if err != nil {
		return nil, err
	}

	dirty := false

	if loadBalancer == nil {
		createRequest := &elb.CreateLoadBalancerInput{}
		createRequest.LoadBalancerName = aws.String(loadBalancerName)

		createRequest.Listeners = listeners

		if internalELB {
			createRequest.Scheme = aws.String("internal")
		}

		// We are supposed to specify one subnet per AZ.
		// TODO: What happens if we have more than one subnet per AZ?
		createRequest.Subnets = stringPointerArray(subnetIDs)

		createRequest.SecurityGroups = stringPointerArray(securityGroupIDs)

		createRequest.Tags = []*elb.Tag{
			{Key: aws.String(TagNameKubernetesCluster), Value: aws.String(c.getClusterName())},
			{Key: aws.String(TagNameKubernetesService), Value: aws.String(namespacedName.String())},
		}

		glog.Infof("Creating load balancer for %v with name: ", namespacedName, loadBalancerName)
		_, err := c.elb.CreateLoadBalancer(createRequest)
		if err != nil {
			return nil, err
		}

		if proxyProtocol {
			err = c.createProxyProtocolPolicy(loadBalancerName)
			if err != nil {
				return nil, err
			}

			for _, listener := range listeners {
				glog.V(2).Infof("Adjusting AWS loadbalancer proxy protocol on node port %d. Setting to true", *listener.InstancePort)
				err := c.setBackendPolicies(loadBalancerName, *listener.InstancePort, []*string{aws.String(ProxyProtocolPolicyName)})
				if err != nil {
					return nil, err
				}
			}
		}

		dirty = true
	} else {
		// TODO: Sync internal vs non-internal

		{
			// Sync subnets
			expected := sets.NewString(subnetIDs...)
			actual := stringSetFromPointers(loadBalancer.Subnets)

			additions := expected.Difference(actual)
			removals := actual.Difference(expected)

			if removals.Len() != 0 {
				request := &elb.DetachLoadBalancerFromSubnetsInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.Subnets = stringSetToPointers(removals)
				glog.V(2).Info("Detaching load balancer from removed subnets")
				_, err := c.elb.DetachLoadBalancerFromSubnets(request)
				if err != nil {
					return nil, fmt.Errorf("error detaching AWS loadbalancer from subnets: %v", err)
				}
				dirty = true
			}

			if additions.Len() != 0 {
				request := &elb.AttachLoadBalancerToSubnetsInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.Subnets = stringSetToPointers(additions)
				glog.V(2).Info("Attaching load balancer to added subnets")
				_, err := c.elb.AttachLoadBalancerToSubnets(request)
				if err != nil {
					return nil, fmt.Errorf("error attaching AWS loadbalancer to subnets: %v", err)
				}
				dirty = true
			}
		}

		{
			// Sync security groups
			expected := sets.NewString(securityGroupIDs...)
			actual := stringSetFromPointers(loadBalancer.SecurityGroups)

			if !expected.Equal(actual) {
				// This call just replaces the security groups, unlike e.g. subnets (!)
				request := &elb.ApplySecurityGroupsToLoadBalancerInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.SecurityGroups = stringPointerArray(securityGroupIDs)
				glog.V(2).Info("Applying updated security groups to load balancer")
				_, err := c.elb.ApplySecurityGroupsToLoadBalancer(request)
				if err != nil {
					return nil, fmt.Errorf("error applying AWS loadbalancer security groups: %v", err)
				}
				dirty = true
			}
		}

		{
			// Sync listeners
			listenerDescriptions := loadBalancer.ListenerDescriptions

			foundSet := make(map[int]bool)
			removals := []*int64{}
			for _, listenerDescription := range listenerDescriptions {
				actual := listenerDescription.Listener
				if actual == nil {
					glog.Warning("Ignoring empty listener in AWS loadbalancer: ", loadBalancerName)
					continue
				}

				found := -1
				for i, expected := range listeners {
					if orEmpty(actual.Protocol) != orEmpty(expected.Protocol) {
						continue
					}
					if orEmpty(actual.InstanceProtocol) != orEmpty(expected.InstanceProtocol) {
						continue
					}
					if orZero(actual.InstancePort) != orZero(expected.InstancePort) {
						continue
					}
					if orZero(actual.LoadBalancerPort) != orZero(expected.LoadBalancerPort) {
						continue
					}
					if orEmpty(actual.SSLCertificateId) != orEmpty(expected.SSLCertificateId) {
						continue
					}
					found = i
				}
				if found != -1 {
					foundSet[found] = true
				} else {
					removals = append(removals, actual.LoadBalancerPort)
				}
			}

			additions := []*elb.Listener{}
			for i := range listeners {
				if foundSet[i] {
					continue
				}
				additions = append(additions, listeners[i])
			}

			if len(removals) != 0 {
				request := &elb.DeleteLoadBalancerListenersInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.LoadBalancerPorts = removals
				glog.V(2).Info("Deleting removed load balancer listeners")
				_, err := c.elb.DeleteLoadBalancerListeners(request)
				if err != nil {
					return nil, fmt.Errorf("error deleting AWS loadbalancer listeners: %v", err)
				}
				dirty = true
			}

			if len(additions) != 0 {
				request := &elb.CreateLoadBalancerListenersInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.Listeners = additions
				glog.V(2).Info("Creating added load balancer listeners")
				_, err := c.elb.CreateLoadBalancerListeners(request)
				if err != nil {
					return nil, fmt.Errorf("error creating AWS loadbalancer listeners: %v", err)
				}
				dirty = true
			}
		}

		{
			// Sync proxy protocol state for new and existing listeners

			proxyPolicies := make([]*string, 0)
			if proxyProtocol {
				// Ensure the backend policy exists

				// NOTE The documentation for the AWS API indicates we could get an HTTP 400
				// back if a policy of the same name already exists. However, the aws-sdk does not
				// seem to return an error to us in these cases. Therefore this will issue an API
				// request every time.
				err := c.createProxyProtocolPolicy(loadBalancerName)
				if err != nil {
					return nil, err
				}

				proxyPolicies = append(proxyPolicies, aws.String(ProxyProtocolPolicyName))
			}

			foundBackends := make(map[int64]bool)
			proxyProtocolBackends := make(map[int64]bool)
			for _, backendListener := range loadBalancer.BackendServerDescriptions {
				foundBackends[*backendListener.InstancePort] = false
				proxyProtocolBackends[*backendListener.InstancePort] = proxyProtocolEnabled(backendListener)
			}

			for _, listener := range listeners {
				setPolicy := false
				instancePort := *listener.InstancePort

				if currentState, ok := proxyProtocolBackends[instancePort]; !ok {
					// This is a new ELB backend so we only need to worry about
					// potentientally adding a policy and not removing an
					// existing one
					setPolicy = proxyProtocol
				} else {
					foundBackends[instancePort] = true
					// This is an existing ELB backend so we need to determine
					// if the state changed
					setPolicy = (currentState != proxyProtocol)
				}

				if setPolicy {
					glog.V(2).Infof("Adjusting AWS loadbalancer proxy protocol on node port %d. Setting to %t", instancePort, proxyProtocol)
					err := c.setBackendPolicies(loadBalancerName, instancePort, proxyPolicies)
					if err != nil {
						return nil, err
					}
					dirty = true
				}
			}

			// We now need to figure out if any backend policies need removed
			// because these old policies will stick around even if there is no
			// corresponding listener anymore
			for instancePort, found := range foundBackends {
				if !found {
					glog.V(2).Infof("Adjusting AWS loadbalancer proxy protocol on node port %d. Setting to false", instancePort)
					err := c.setBackendPolicies(loadBalancerName, instancePort, []*string{})
					if err != nil {
						return nil, err
					}
					dirty = true
				}
			}
		}
	}

	if dirty {
		loadBalancer, err = c.describeLoadBalancer(loadBalancerName)
		if err != nil {
			glog.Warning("Unable to retrieve load balancer after creation/update")
			return nil, err
		}
	}

	return loadBalancer, nil
}

// Makes sure that the health check for an ELB matches the configured listeners
func (c *Cloud) ensureLoadBalancerHealthCheck(loadBalancer *elb.LoadBalancerDescription, listeners []*elb.Listener) error {
	actual := loadBalancer.HealthCheck

	// Default AWS settings
	expectedHealthyThreshold := int64(2)
	expectedUnhealthyThreshold := int64(6)
	expectedTimeout := int64(5)
	expectedInterval := int64(10)

	// We only configure a TCP health-check on the first port
	expectedTarget := ""
	for _, listener := range listeners {
		if listener.InstancePort == nil {
			continue
		}
		expectedTarget = "TCP:" + strconv.FormatInt(*listener.InstancePort, 10)
		break
	}

	if expectedTarget == "" {
		return fmt.Errorf("unable to determine health check port (no valid listeners)")
	}

	if expectedTarget == orEmpty(actual.Target) &&
		expectedHealthyThreshold == orZero(actual.HealthyThreshold) &&
		expectedUnhealthyThreshold == orZero(actual.UnhealthyThreshold) &&
		expectedTimeout == orZero(actual.Timeout) &&
		expectedInterval == orZero(actual.Interval) {
		return nil
	}

	glog.V(2).Info("Updating load-balancer health-check")

	healthCheck := &elb.HealthCheck{}
	healthCheck.HealthyThreshold = &expectedHealthyThreshold
	healthCheck.UnhealthyThreshold = &expectedUnhealthyThreshold
	healthCheck.Timeout = &expectedTimeout
	healthCheck.Interval = &expectedInterval
	healthCheck.Target = &expectedTarget

	request := &elb.ConfigureHealthCheckInput{}
	request.HealthCheck = healthCheck
	request.LoadBalancerName = loadBalancer.LoadBalancerName

	_, err := c.elb.ConfigureHealthCheck(request)
	if err != nil {
		return fmt.Errorf("error configuring load-balancer health-check: %v", err)
	}

	return nil
}

// Makes sure that exactly the specified hosts are registered as instances with the load balancer
func (c *Cloud) ensureLoadBalancerInstances(loadBalancerName string, lbInstances []*elb.Instance, instances []*ec2.Instance) error {
	expected := sets.NewString()
	for _, instance := range instances {
		expected.Insert(orEmpty(instance.InstanceId))
	}

	actual := sets.NewString()
	for _, lbInstance := range lbInstances {
		actual.Insert(orEmpty(lbInstance.InstanceId))
	}

	additions := expected.Difference(actual)
	removals := actual.Difference(expected)

	addInstances := []*elb.Instance{}
	for _, instanceId := range additions.List() {
		addInstance := &elb.Instance{}
		addInstance.InstanceId = aws.String(instanceId)
		addInstances = append(addInstances, addInstance)
	}

	removeInstances := []*elb.Instance{}
	for _, instanceId := range removals.List() {
		removeInstance := &elb.Instance{}
		removeInstance.InstanceId = aws.String(instanceId)
		removeInstances = append(removeInstances, removeInstance)
	}

	if len(addInstances) > 0 {
		registerRequest := &elb.RegisterInstancesWithLoadBalancerInput{}
		registerRequest.Instances = addInstances
		registerRequest.LoadBalancerName = aws.String(loadBalancerName)
		_, err := c.elb.RegisterInstancesWithLoadBalancer(registerRequest)
		if err != nil {
			return err
		}
		glog.V(1).Infof("Instances added to load-balancer %s", loadBalancerName)
	}

	if len(removeInstances) > 0 {
		deregisterRequest := &elb.DeregisterInstancesFromLoadBalancerInput{}
		deregisterRequest.Instances = removeInstances
		deregisterRequest.LoadBalancerName = aws.String(loadBalancerName)
		_, err := c.elb.DeregisterInstancesFromLoadBalancer(deregisterRequest)
		if err != nil {
			return err
		}
		glog.V(1).Infof("Instances removed from load-balancer %s", loadBalancerName)
	}

	return nil
}

func (c *Cloud) createProxyProtocolPolicy(loadBalancerName string) error {
	request := &elb.CreateLoadBalancerPolicyInput{
		LoadBalancerName: aws.String(loadBalancerName),
		PolicyName:       aws.String(ProxyProtocolPolicyName),
		PolicyTypeName:   aws.String("ProxyProtocolPolicyType"),
		PolicyAttributes: []*elb.PolicyAttribute{
			{
				AttributeName:  aws.String("ProxyProtocol"),
				AttributeValue: aws.String("true"),
			},
		},
	}
	glog.V(2).Info("Creating proxy protocol policy on load balancer")
	_, err := c.elb.CreateLoadBalancerPolicy(request)
	if err != nil {
		return fmt.Errorf("error creating proxy protocol policy on load balancer: %v", err)
	}

	return nil
}

func (c *Cloud) setBackendPolicies(loadBalancerName string, instancePort int64, policies []*string) error {
	request := &elb.SetLoadBalancerPoliciesForBackendServerInput{
		InstancePort:     aws.Int64(instancePort),
		LoadBalancerName: aws.String(loadBalancerName),
		PolicyNames:      policies,
	}
	if len(policies) > 0 {
		glog.V(2).Infof("Adding AWS loadbalancer backend policies on node port %d", instancePort)
	} else {
		glog.V(2).Infof("Removing AWS loadbalancer backend policies on node port %d", instancePort)
	}
	_, err := c.elb.SetLoadBalancerPoliciesForBackendServer(request)
	if err != nil {
		return fmt.Errorf("error adjusting AWS loadbalancer backend policies: %v", err)
	}

	return nil
}

func proxyProtocolEnabled(backend *elb.BackendServerDescription) bool {
	for _, policy := range backend.PolicyNames {
		if aws.StringValue(policy) == ProxyProtocolPolicyName {
			return true
		}
	}

	return false
}
<commit_msg>format number not consistent with real variable number<commit_after>/*
Copyright 2014 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 aws

import (
	"fmt"
	"strconv"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/golang/glog"
	"k8s.io/kubernetes/pkg/types"
	"k8s.io/kubernetes/pkg/util/sets"
)

const ProxyProtocolPolicyName = "k8s-proxyprotocol-enabled"

func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBalancerName string, listeners []*elb.Listener, subnetIDs []string, securityGroupIDs []string, internalELB, proxyProtocol bool) (*elb.LoadBalancerDescription, error) {
	loadBalancer, err := c.describeLoadBalancer(loadBalancerName)
	if err != nil {
		return nil, err
	}

	dirty := false

	if loadBalancer == nil {
		createRequest := &elb.CreateLoadBalancerInput{}
		createRequest.LoadBalancerName = aws.String(loadBalancerName)

		createRequest.Listeners = listeners

		if internalELB {
			createRequest.Scheme = aws.String("internal")
		}

		// We are supposed to specify one subnet per AZ.
		// TODO: What happens if we have more than one subnet per AZ?
		createRequest.Subnets = stringPointerArray(subnetIDs)

		createRequest.SecurityGroups = stringPointerArray(securityGroupIDs)

		createRequest.Tags = []*elb.Tag{
			{Key: aws.String(TagNameKubernetesCluster), Value: aws.String(c.getClusterName())},
			{Key: aws.String(TagNameKubernetesService), Value: aws.String(namespacedName.String())},
		}

		glog.Infof("Creating load balancer for %v with name: %s", namespacedName, loadBalancerName)
		_, err := c.elb.CreateLoadBalancer(createRequest)
		if err != nil {
			return nil, err
		}

		if proxyProtocol {
			err = c.createProxyProtocolPolicy(loadBalancerName)
			if err != nil {
				return nil, err
			}

			for _, listener := range listeners {
				glog.V(2).Infof("Adjusting AWS loadbalancer proxy protocol on node port %d. Setting to true", *listener.InstancePort)
				err := c.setBackendPolicies(loadBalancerName, *listener.InstancePort, []*string{aws.String(ProxyProtocolPolicyName)})
				if err != nil {
					return nil, err
				}
			}
		}

		dirty = true
	} else {
		// TODO: Sync internal vs non-internal

		{
			// Sync subnets
			expected := sets.NewString(subnetIDs...)
			actual := stringSetFromPointers(loadBalancer.Subnets)

			additions := expected.Difference(actual)
			removals := actual.Difference(expected)

			if removals.Len() != 0 {
				request := &elb.DetachLoadBalancerFromSubnetsInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.Subnets = stringSetToPointers(removals)
				glog.V(2).Info("Detaching load balancer from removed subnets")
				_, err := c.elb.DetachLoadBalancerFromSubnets(request)
				if err != nil {
					return nil, fmt.Errorf("error detaching AWS loadbalancer from subnets: %v", err)
				}
				dirty = true
			}

			if additions.Len() != 0 {
				request := &elb.AttachLoadBalancerToSubnetsInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.Subnets = stringSetToPointers(additions)
				glog.V(2).Info("Attaching load balancer to added subnets")
				_, err := c.elb.AttachLoadBalancerToSubnets(request)
				if err != nil {
					return nil, fmt.Errorf("error attaching AWS loadbalancer to subnets: %v", err)
				}
				dirty = true
			}
		}

		{
			// Sync security groups
			expected := sets.NewString(securityGroupIDs...)
			actual := stringSetFromPointers(loadBalancer.SecurityGroups)

			if !expected.Equal(actual) {
				// This call just replaces the security groups, unlike e.g. subnets (!)
				request := &elb.ApplySecurityGroupsToLoadBalancerInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.SecurityGroups = stringPointerArray(securityGroupIDs)
				glog.V(2).Info("Applying updated security groups to load balancer")
				_, err := c.elb.ApplySecurityGroupsToLoadBalancer(request)
				if err != nil {
					return nil, fmt.Errorf("error applying AWS loadbalancer security groups: %v", err)
				}
				dirty = true
			}
		}

		{
			// Sync listeners
			listenerDescriptions := loadBalancer.ListenerDescriptions

			foundSet := make(map[int]bool)
			removals := []*int64{}
			for _, listenerDescription := range listenerDescriptions {
				actual := listenerDescription.Listener
				if actual == nil {
					glog.Warning("Ignoring empty listener in AWS loadbalancer: ", loadBalancerName)
					continue
				}

				found := -1
				for i, expected := range listeners {
					if orEmpty(actual.Protocol) != orEmpty(expected.Protocol) {
						continue
					}
					if orEmpty(actual.InstanceProtocol) != orEmpty(expected.InstanceProtocol) {
						continue
					}
					if orZero(actual.InstancePort) != orZero(expected.InstancePort) {
						continue
					}
					if orZero(actual.LoadBalancerPort) != orZero(expected.LoadBalancerPort) {
						continue
					}
					if orEmpty(actual.SSLCertificateId) != orEmpty(expected.SSLCertificateId) {
						continue
					}
					found = i
				}
				if found != -1 {
					foundSet[found] = true
				} else {
					removals = append(removals, actual.LoadBalancerPort)
				}
			}

			additions := []*elb.Listener{}
			for i := range listeners {
				if foundSet[i] {
					continue
				}
				additions = append(additions, listeners[i])
			}

			if len(removals) != 0 {
				request := &elb.DeleteLoadBalancerListenersInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.LoadBalancerPorts = removals
				glog.V(2).Info("Deleting removed load balancer listeners")
				_, err := c.elb.DeleteLoadBalancerListeners(request)
				if err != nil {
					return nil, fmt.Errorf("error deleting AWS loadbalancer listeners: %v", err)
				}
				dirty = true
			}

			if len(additions) != 0 {
				request := &elb.CreateLoadBalancerListenersInput{}
				request.LoadBalancerName = aws.String(loadBalancerName)
				request.Listeners = additions
				glog.V(2).Info("Creating added load balancer listeners")
				_, err := c.elb.CreateLoadBalancerListeners(request)
				if err != nil {
					return nil, fmt.Errorf("error creating AWS loadbalancer listeners: %v", err)
				}
				dirty = true
			}
		}

		{
			// Sync proxy protocol state for new and existing listeners

			proxyPolicies := make([]*string, 0)
			if proxyProtocol {
				// Ensure the backend policy exists

				// NOTE The documentation for the AWS API indicates we could get an HTTP 400
				// back if a policy of the same name already exists. However, the aws-sdk does not
				// seem to return an error to us in these cases. Therefore this will issue an API
				// request every time.
				err := c.createProxyProtocolPolicy(loadBalancerName)
				if err != nil {
					return nil, err
				}

				proxyPolicies = append(proxyPolicies, aws.String(ProxyProtocolPolicyName))
			}

			foundBackends := make(map[int64]bool)
			proxyProtocolBackends := make(map[int64]bool)
			for _, backendListener := range loadBalancer.BackendServerDescriptions {
				foundBackends[*backendListener.InstancePort] = false
				proxyProtocolBackends[*backendListener.InstancePort] = proxyProtocolEnabled(backendListener)
			}

			for _, listener := range listeners {
				setPolicy := false
				instancePort := *listener.InstancePort

				if currentState, ok := proxyProtocolBackends[instancePort]; !ok {
					// This is a new ELB backend so we only need to worry about
					// potentientally adding a policy and not removing an
					// existing one
					setPolicy = proxyProtocol
				} else {
					foundBackends[instancePort] = true
					// This is an existing ELB backend so we need to determine
					// if the state changed
					setPolicy = (currentState != proxyProtocol)
				}

				if setPolicy {
					glog.V(2).Infof("Adjusting AWS loadbalancer proxy protocol on node port %d. Setting to %t", instancePort, proxyProtocol)
					err := c.setBackendPolicies(loadBalancerName, instancePort, proxyPolicies)
					if err != nil {
						return nil, err
					}
					dirty = true
				}
			}

			// We now need to figure out if any backend policies need removed
			// because these old policies will stick around even if there is no
			// corresponding listener anymore
			for instancePort, found := range foundBackends {
				if !found {
					glog.V(2).Infof("Adjusting AWS loadbalancer proxy protocol on node port %d. Setting to false", instancePort)
					err := c.setBackendPolicies(loadBalancerName, instancePort, []*string{})
					if err != nil {
						return nil, err
					}
					dirty = true
				}
			}
		}
	}

	if dirty {
		loadBalancer, err = c.describeLoadBalancer(loadBalancerName)
		if err != nil {
			glog.Warning("Unable to retrieve load balancer after creation/update")
			return nil, err
		}
	}

	return loadBalancer, nil
}

// Makes sure that the health check for an ELB matches the configured listeners
func (c *Cloud) ensureLoadBalancerHealthCheck(loadBalancer *elb.LoadBalancerDescription, listeners []*elb.Listener) error {
	actual := loadBalancer.HealthCheck

	// Default AWS settings
	expectedHealthyThreshold := int64(2)
	expectedUnhealthyThreshold := int64(6)
	expectedTimeout := int64(5)
	expectedInterval := int64(10)

	// We only configure a TCP health-check on the first port
	expectedTarget := ""
	for _, listener := range listeners {
		if listener.InstancePort == nil {
			continue
		}
		expectedTarget = "TCP:" + strconv.FormatInt(*listener.InstancePort, 10)
		break
	}

	if expectedTarget == "" {
		return fmt.Errorf("unable to determine health check port (no valid listeners)")
	}

	if expectedTarget == orEmpty(actual.Target) &&
		expectedHealthyThreshold == orZero(actual.HealthyThreshold) &&
		expectedUnhealthyThreshold == orZero(actual.UnhealthyThreshold) &&
		expectedTimeout == orZero(actual.Timeout) &&
		expectedInterval == orZero(actual.Interval) {
		return nil
	}

	glog.V(2).Info("Updating load-balancer health-check")

	healthCheck := &elb.HealthCheck{}
	healthCheck.HealthyThreshold = &expectedHealthyThreshold
	healthCheck.UnhealthyThreshold = &expectedUnhealthyThreshold
	healthCheck.Timeout = &expectedTimeout
	healthCheck.Interval = &expectedInterval
	healthCheck.Target = &expectedTarget

	request := &elb.ConfigureHealthCheckInput{}
	request.HealthCheck = healthCheck
	request.LoadBalancerName = loadBalancer.LoadBalancerName

	_, err := c.elb.ConfigureHealthCheck(request)
	if err != nil {
		return fmt.Errorf("error configuring load-balancer health-check: %v", err)
	}

	return nil
}

// Makes sure that exactly the specified hosts are registered as instances with the load balancer
func (c *Cloud) ensureLoadBalancerInstances(loadBalancerName string, lbInstances []*elb.Instance, instances []*ec2.Instance) error {
	expected := sets.NewString()
	for _, instance := range instances {
		expected.Insert(orEmpty(instance.InstanceId))
	}

	actual := sets.NewString()
	for _, lbInstance := range lbInstances {
		actual.Insert(orEmpty(lbInstance.InstanceId))
	}

	additions := expected.Difference(actual)
	removals := actual.Difference(expected)

	addInstances := []*elb.Instance{}
	for _, instanceId := range additions.List() {
		addInstance := &elb.Instance{}
		addInstance.InstanceId = aws.String(instanceId)
		addInstances = append(addInstances, addInstance)
	}

	removeInstances := []*elb.Instance{}
	for _, instanceId := range removals.List() {
		removeInstance := &elb.Instance{}
		removeInstance.InstanceId = aws.String(instanceId)
		removeInstances = append(removeInstances, removeInstance)
	}

	if len(addInstances) > 0 {
		registerRequest := &elb.RegisterInstancesWithLoadBalancerInput{}
		registerRequest.Instances = addInstances
		registerRequest.LoadBalancerName = aws.String(loadBalancerName)
		_, err := c.elb.RegisterInstancesWithLoadBalancer(registerRequest)
		if err != nil {
			return err
		}
		glog.V(1).Infof("Instances added to load-balancer %s", loadBalancerName)
	}

	if len(removeInstances) > 0 {
		deregisterRequest := &elb.DeregisterInstancesFromLoadBalancerInput{}
		deregisterRequest.Instances = removeInstances
		deregisterRequest.LoadBalancerName = aws.String(loadBalancerName)
		_, err := c.elb.DeregisterInstancesFromLoadBalancer(deregisterRequest)
		if err != nil {
			return err
		}
		glog.V(1).Infof("Instances removed from load-balancer %s", loadBalancerName)
	}

	return nil
}

func (c *Cloud) createProxyProtocolPolicy(loadBalancerName string) error {
	request := &elb.CreateLoadBalancerPolicyInput{
		LoadBalancerName: aws.String(loadBalancerName),
		PolicyName:       aws.String(ProxyProtocolPolicyName),
		PolicyTypeName:   aws.String("ProxyProtocolPolicyType"),
		PolicyAttributes: []*elb.PolicyAttribute{
			{
				AttributeName:  aws.String("ProxyProtocol"),
				AttributeValue: aws.String("true"),
			},
		},
	}
	glog.V(2).Info("Creating proxy protocol policy on load balancer")
	_, err := c.elb.CreateLoadBalancerPolicy(request)
	if err != nil {
		return fmt.Errorf("error creating proxy protocol policy on load balancer: %v", err)
	}

	return nil
}

func (c *Cloud) setBackendPolicies(loadBalancerName string, instancePort int64, policies []*string) error {
	request := &elb.SetLoadBalancerPoliciesForBackendServerInput{
		InstancePort:     aws.Int64(instancePort),
		LoadBalancerName: aws.String(loadBalancerName),
		PolicyNames:      policies,
	}
	if len(policies) > 0 {
		glog.V(2).Infof("Adding AWS loadbalancer backend policies on node port %d", instancePort)
	} else {
		glog.V(2).Infof("Removing AWS loadbalancer backend policies on node port %d", instancePort)
	}
	_, err := c.elb.SetLoadBalancerPoliciesForBackendServer(request)
	if err != nil {
		return fmt.Errorf("error adjusting AWS loadbalancer backend policies: %v", err)
	}

	return nil
}

func proxyProtocolEnabled(backend *elb.BackendServerDescription) bool {
	for _, policy := range backend.PolicyNames {
		if aws.StringValue(policy) == ProxyProtocolPolicyName {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// 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 ebitenutil

import (
	"github.com/hajimehoshi/ebiten"
	"image"
	"image/color/palette"
	"image/draw"
	"image/gif"
	"io"
)

type recorder struct {
	inner        func(screen *ebiten.Image) error
	writer       io.Writer
	gif          *gif.GIF
	currentFrame int
}

func (r *recorder) update(screen *ebiten.Image) error {
	if err := r.inner(screen); err != nil {
		return err
	}
	if r.currentFrame == len(r.gif.Image) {
		return nil
	}
	img := image.NewPaletted(screen.Bounds(), palette.Plan9)
	// TODO: This is too slow.
	draw.Draw(img, img.Bounds(), screen, screen.Bounds().Min, draw.Src)
	r.gif.Image[r.currentFrame] = img
	// The actual FPS is 60, but GIF can't have such FPS. Set 50 FPS instead.
	r.gif.Delay[r.currentFrame] = 2

	r.currentFrame++
	if r.currentFrame == len(r.gif.Image) {
		if err := gif.EncodeAll(r.writer, r.gif); err != nil {
			return err
		}
	}
	return nil
}

// RecordScreenAsGIF returns updating function with recording the screen as an animation GIF image.
//
// This encodes each screen at each frame and may slows the application.
func RecordScreenAsGIF(update func(*ebiten.Image) error, out io.Writer, frameNum int) func(*ebiten.Image) error {
	r := &recorder{
		inner:  update,
		writer: out,
		gif: &gif.GIF{
			Image:     make([]*image.Paletted, frameNum),
			Delay:     make([]int, frameNum),
			LoopCount: -1,
		},
	}
	return r.update
}
<commit_msg>Add example for RecordScreenAsGIF<commit_after>// Copyright 2014 Hajime Hoshi
//
// 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 ebitenutil

import (
	"github.com/hajimehoshi/ebiten"
	"image"
	"image/color/palette"
	"image/draw"
	"image/gif"
	"io"
)

type recorder struct {
	inner        func(screen *ebiten.Image) error
	writer       io.Writer
	gif          *gif.GIF
	currentFrame int
}

func (r *recorder) update(screen *ebiten.Image) error {
	if err := r.inner(screen); err != nil {
		return err
	}
	if r.currentFrame == len(r.gif.Image) {
		return nil
	}
	img := image.NewPaletted(screen.Bounds(), palette.Plan9)
	// TODO: This is too slow.
	draw.Draw(img, img.Bounds(), screen, screen.Bounds().Min, draw.Src)
	r.gif.Image[r.currentFrame] = img
	// The actual FPS is 60, but GIF can't have such FPS. Set 50 FPS instead.
	r.gif.Delay[r.currentFrame] = 2

	r.currentFrame++
	if r.currentFrame == len(r.gif.Image) {
		if err := gif.EncodeAll(r.writer, r.gif); err != nil {
			return err
		}
	}
	return nil
}

// RecordScreenAsGIF returns updating function with recording the screen as an animation GIF image.
//
// This encodes each screen at each frame and may slows the application.
//
// Here is the example to record initial 120 frames of your game:
//
//     func update(screen *ebiten.Image) error {
//         // ...
//     }
//
//     func main() {
//         out, err := os.Create("output.gif")
//         if err != nil {
//             log.Fatal(err)
//         }
//         defer out.Close()
//
//         update := RecordScreenAsGIF(update, out, 120)
//         if err := ebiten.Run(update, 320, 240, 2, "Your game's title"); err != nil {
//             log.Fatal(err)
//         }
//     }
func RecordScreenAsGIF(update func(*ebiten.Image) error, out io.Writer, frameNum int) func(*ebiten.Image) error {
	r := &recorder{
		inner:  update,
		writer: out,
		gif: &gif.GIF{
			Image:     make([]*image.Paletted, frameNum),
			Delay:     make([]int, frameNum),
			LoopCount: -1,
		},
	}
	return r.update
}
<|endoftext|>


<commit_before>package asset

// DefaultImages are the defualt images bootkube components use.
var DefaultImages = ImageVersions{
	Etcd:            "quay.io/coreos/etcd:v3.1.8",
	EtcdOperator:    "quay.io/coreos/etcd-operator:v0.5.0",
	Flannel:         "quay.io/coreos/flannel:v0.9.1-amd64",
	FlannelCNI:      "quay.io/coreos/flannel-cni:v0.3.0",
	Calico:          "quay.io/calico/node:v2.6.1",
	CalicoCNI:       "quay.io/calico/cni:v1.11.0",
	Hyperkube:       "gcr.io/google_containers/hyperkube:v1.8.4",
	Kenc:            "quay.io/coreos/kenc:0.0.2",
	KubeDNS:         "gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.5",
	KubeDNSMasq:     "gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.5",
	KubeDNSSidecar:  "gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.5",
	PodCheckpointer: "quay.io/coreos/pod-checkpointer:e22cc0e3714378de92f45326474874eb602ca0ac",
}
<commit_msg>Update Calico from v2.6.1 to v2.6.3<commit_after>package asset

// DefaultImages are the defualt images bootkube components use.
var DefaultImages = ImageVersions{
	Etcd:            "quay.io/coreos/etcd:v3.1.8",
	EtcdOperator:    "quay.io/coreos/etcd-operator:v0.5.0",
	Flannel:         "quay.io/coreos/flannel:v0.9.1-amd64",
	FlannelCNI:      "quay.io/coreos/flannel-cni:v0.3.0",
	Calico:          "quay.io/calico/node:v2.6.3",
	CalicoCNI:       "quay.io/calico/cni:v1.11.1",
	Hyperkube:       "gcr.io/google_containers/hyperkube:v1.8.4",
	Kenc:            "quay.io/coreos/kenc:0.0.2",
	KubeDNS:         "gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.5",
	KubeDNSMasq:     "gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.5",
	KubeDNSSidecar:  "gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.5",
	PodCheckpointer: "quay.io/coreos/pod-checkpointer:e22cc0e3714378de92f45326474874eb602ca0ac",
}
<|endoftext|>


<commit_before>// Copyright © 2018 The Knative 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 core

import (
	"flag"
	"fmt"
	"io"
	"os"
	"path"
	"strconv"
	"strings"

	homedir "github.com/mitchellh/go-homedir"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"golang.org/x/crypto/ssh/terminal"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
	"knative.dev/client/pkg/kn/commands"
	"knative.dev/client/pkg/kn/commands/completion"
	"knative.dev/client/pkg/kn/commands/plugin"
	"knative.dev/client/pkg/kn/commands/revision"
	"knative.dev/client/pkg/kn/commands/route"
	"knative.dev/client/pkg/kn/commands/service"
	"knative.dev/client/pkg/kn/commands/source"
	"knative.dev/client/pkg/kn/commands/trigger"
	"knative.dev/client/pkg/kn/commands/version"
	"knative.dev/client/pkg/kn/flags"
)

// NewDefaultKnCommand creates the default `kn` command with a default plugin handler
func NewDefaultKnCommand() *cobra.Command {
	rootCmd := NewKnCommand()

	// Needed since otherwise --plugins-dir and --lookup-plugins
	// will not be accounted for since the plugin is not a Cobra command
	// and will not be parsed
	pluginsDir, lookupPluginsInPath, err := extractKnPluginFlags(os.Args)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}

	pluginHandler := plugin.NewDefaultPluginHandler(plugin.ValidPluginFilenamePrefixes,
		pluginsDir, lookupPluginsInPath)

	return NewDefaultKnCommandWithArgs(rootCmd, pluginHandler,
		os.Args, os.Stdin,
		os.Stdout, os.Stderr)
}

// NewDefaultKnCommandWithArgs creates the `kn` command with arguments
func NewDefaultKnCommandWithArgs(rootCmd *cobra.Command,
	pluginHandler plugin.PluginHandler,
	args []string,
	in io.Reader,
	out,
	errOut io.Writer) *cobra.Command {
	if pluginHandler == nil {
		return rootCmd
	}
	if len(args) > 1 {
		cmdPathPieces := args[1:]
		cmdPathPieces = removeKnPluginFlags(cmdPathPieces) // Plugin does not need these flags

		// only look for suitable extension executables if
		// the specified command does not already exist
		foundCmd, innerArgs, err := rootCmd.Find(cmdPathPieces)
		if err != nil {
			err := plugin.HandlePluginCommand(pluginHandler, cmdPathPieces)
			if err != nil {
				fmt.Fprintf(rootCmd.OutOrStderr(), "Error: unknown command '%s' \nRun 'kn --help' for usage.\n", args[1])
				os.Exit(1)
			}
		} else if foundCmd.HasSubCommands() {
			if _, _, err := rootCmd.Find(innerArgs); err != nil {
				fmt.Fprintf(rootCmd.OutOrStderr(), showSubcommands(foundCmd, cmdPathPieces, innerArgs[0]))
				os.Exit(1)
			}
		}
	}

	return rootCmd
}

// NewKnCommand creates the rootCmd which is the base command when called without any subcommands
func NewKnCommand(params ...commands.KnParams) *cobra.Command {
	var p *commands.KnParams
	if len(params) == 0 {
		p = &commands.KnParams{}
	} else if len(params) == 1 {
		p = &params[0]
	} else {
		panic("Too many params objects to NewKnCommand")
	}
	p.Initialize()

	rootCmd := &cobra.Command{
		Use:   "kn",
		Short: "Knative client",
		Long: `Manage your Knative building blocks:

* Serving: Manage your services and release new software to them.
* Eventing: Manage event subscriptions and channels. Connect up event sources.`,

		// Disable docs header
		DisableAutoGenTag: true,

		// Affects children as well
		SilenceUsage: true,

		// Prevents Cobra from dealing with errors as we deal with them in main.go
		SilenceErrors: true,

		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			initConfigFlags()
			return flags.ReconcileBoolFlags(cmd.Flags())
		},
	}
	if p.Output != nil {
		rootCmd.SetOutput(p.Output)
	}

	// Persistent flags
	rootCmd.PersistentFlags().StringVar(&commands.CfgFile, "config", "", "kn config file (default is $HOME/.kn/config.yaml)")
	rootCmd.PersistentFlags().StringVar(&p.KubeCfgPath, "kubeconfig", "", "kubectl config file (default is $HOME/.kube/config)")
	flags.AddBothBoolFlags(rootCmd.PersistentFlags(), &p.LogHTTP, "log-http", "", false, "log http traffic")

	plugin.AddPluginFlags(rootCmd)
	plugin.BindPluginsFlagToViper(rootCmd)

	// root child commands
	rootCmd.AddCommand(service.NewServiceCommand(p))
	rootCmd.AddCommand(revision.NewRevisionCommand(p))
	rootCmd.AddCommand(plugin.NewPluginCommand(p))
	rootCmd.AddCommand(route.NewRouteCommand(p))
	rootCmd.AddCommand(completion.NewCompletionCommand(p))
	rootCmd.AddCommand(version.NewVersionCommand(p))
	rootCmd.AddCommand(source.NewSourceCommand(p))
	rootCmd.AddCommand(trigger.NewTriggerCommand(p))

	// Deal with empty and unknown sub command groups
	EmptyAndUnknownSubCommands(rootCmd)

	// Wrap usage.
	w, err := width()
	if err == nil {
		newUsage := strings.ReplaceAll(rootCmd.UsageTemplate(), "FlagUsages ",
			fmt.Sprintf("FlagUsagesWrapped %d ", w))
		rootCmd.SetUsageTemplate(newUsage)
	}

	// For glog parse error.
	flag.CommandLine.Parse([]string{})

	return rootCmd
}

// InitializeConfig initializes the kubeconfig used by all commands
func InitializeConfig() {
	cobra.OnInitialize(initConfig)
}

// EmptyAndUnknownSubCommands adds a RunE to all commands that are groups to
// deal with errors when called with empty or unknown sub command
func EmptyAndUnknownSubCommands(cmd *cobra.Command) {
	for _, childCmd := range cmd.Commands() {
		if childCmd.HasSubCommands() && childCmd.RunE == nil {
			childCmd.RunE = func(aCmd *cobra.Command, args []string) error {
				aCmd.Help()
				if len(args) == 0 {
					return fmt.Errorf("please provide a valid sub-command for \"kn %s\"", aCmd.Name())
				}
				return fmt.Errorf("unknown sub-command \"%s\" for \"kn %s\"", args[0], aCmd.Name())
			}
		}

		// recurse to deal with child commands that are themselves command groups
		EmptyAndUnknownSubCommands(childCmd)
	}
}

// Private

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if commands.CfgFile != "" {
		// Use config file from the flag.
		viper.SetConfigFile(commands.CfgFile)
	} else {
		// Find home directory.
		home, err := homedir.Dir()
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			os.Exit(1)
		}

		// Search config in home directory with name ".kn" (without extension)
		viper.AddConfigPath(path.Join(home, ".kn"))
		viper.SetConfigName("config")
	}

	viper.AutomaticEnv() // read in environment variables that match

	// If a config file is found, read it in.
	err := viper.ReadInConfig()
	if err == nil {
		fmt.Fprintln(os.Stderr, "Using kn config file:", viper.ConfigFileUsed())
	}
}

func initConfigFlags() {
	if viper.IsSet("plugins-dir") {
		commands.Cfg.PluginsDir = viper.GetString("plugins-dir")
	}

	// Always set the Cfg.LookupPlugins from viper value since default is false both ways
	var aBool bool
	aBool = viper.GetBool("lookup-plugins")
	commands.Cfg.LookupPlugins = &aBool
}

func extractKnPluginFlags(args []string) (string, bool, error) {
	pluginsDir := "~/.kn/plugins"
	lookupPluginsInPath := false

	dirFlag := "--plugins-dir"
	pathFlag := "--lookup-plugins"
	var err error

	for _, arg := range args {
		if arg == dirFlag {
			// They forgot the =...
			return "", false, fmt.Errorf("Missing %s flag value", dirFlag)
		} else if strings.HasPrefix(arg, dirFlag+"=") {
			// Starts with --plugins-dir=   so we parse the value
			pluginsDir = arg[len(dirFlag)+1:]
			if pluginsDir == "" {
				// They have a "=" but nothing afer it
				return "", false, fmt.Errorf("Missing %s flag value", dirFlag)
			}
		}

		if arg == pathFlag {
			// just --lookup-plugins   no "="
			lookupPluginsInPath = true
		} else if strings.HasPrefix(arg, pathFlag+"=") {
			// Starts with --lookup-plugins=  so we parse value
			arg = arg[len(pathFlag)+1:]
			if lookupPluginsInPath, err = strconv.ParseBool(arg); err != nil {
				return "", false, fmt.Errorf("Invalid boolean value(%q) for %s flag", arg, dirFlag)
			}
		}
	}
	return pluginsDir, lookupPluginsInPath, nil
}

func removeKnPluginFlags(args []string) []string {
	var remainingArgs []string

	// Remove these two flags from the list of args. Even though some of
	// of these cases should have resulted in an error, if for some reason
	// we got here just remove them anyway.
	for _, arg := range args {
		if arg == "--plugins-dir" ||
			strings.HasPrefix(arg, "--plugins-dir=") ||
			arg == "--lookup-plugins" ||
			strings.HasPrefix(arg, "--lookup-plugins=") {
			continue
		} else {
			remainingArgs = append(remainingArgs, arg)
		}
	}

	return remainingArgs
}

func width() (int, error) {
	width, _, err := terminal.GetSize(int(os.Stdout.Fd()))
	return width, err
}

func getCommands(args []string, innerArg string) string {
	commands := []string{"kn"}
	for _, arg := range args {
		if arg == innerArg {
			return strings.Join(commands, " ")
		}
		commands = append(commands, arg)
	}
	return ""
}

func showSubcommands(cmd *cobra.Command, args []string, innerArg string) string {
	var strs []string
	for _, subcmd := range cmd.Commands() {
		strs = append(strs, subcmd.Name())
	}
	return fmt.Sprintf("Error: unknown subcommand '%s' for '%s'. Available subcommands: %s\nRun 'kn --help' for usage.\n", innerArg, getCommands(args, innerArg), strings.Join(strs, ", "))
}
<commit_msg>fix(help): initialize default help cmd early (#664)<commit_after>// Copyright © 2018 The Knative 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 core

import (
	"flag"
	"fmt"
	"io"
	"os"
	"path"
	"strconv"
	"strings"

	homedir "github.com/mitchellh/go-homedir"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"golang.org/x/crypto/ssh/terminal"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
	"knative.dev/client/pkg/kn/commands"
	"knative.dev/client/pkg/kn/commands/completion"
	"knative.dev/client/pkg/kn/commands/plugin"
	"knative.dev/client/pkg/kn/commands/revision"
	"knative.dev/client/pkg/kn/commands/route"
	"knative.dev/client/pkg/kn/commands/service"
	"knative.dev/client/pkg/kn/commands/source"
	"knative.dev/client/pkg/kn/commands/trigger"
	"knative.dev/client/pkg/kn/commands/version"
	"knative.dev/client/pkg/kn/flags"
)

// NewDefaultKnCommand creates the default `kn` command with a default plugin handler
func NewDefaultKnCommand() *cobra.Command {
	rootCmd := NewKnCommand()

	// Needed since otherwise --plugins-dir and --lookup-plugins
	// will not be accounted for since the plugin is not a Cobra command
	// and will not be parsed
	pluginsDir, lookupPluginsInPath, err := extractKnPluginFlags(os.Args)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}

	pluginHandler := plugin.NewDefaultPluginHandler(plugin.ValidPluginFilenamePrefixes,
		pluginsDir, lookupPluginsInPath)

	return NewDefaultKnCommandWithArgs(rootCmd, pluginHandler,
		os.Args, os.Stdin,
		os.Stdout, os.Stderr)
}

// NewDefaultKnCommandWithArgs creates the `kn` command with arguments
func NewDefaultKnCommandWithArgs(rootCmd *cobra.Command,
	pluginHandler plugin.PluginHandler,
	args []string,
	in io.Reader,
	out,
	errOut io.Writer) *cobra.Command {
	if pluginHandler == nil {
		return rootCmd
	}
	if len(args) > 1 {
		cmdPathPieces := args[1:]
		cmdPathPieces = removeKnPluginFlags(cmdPathPieces) // Plugin does not need these flags

		// only look for suitable extension executables if
		// the specified command does not already exist
		foundCmd, innerArgs, err := rootCmd.Find(cmdPathPieces)
		if err != nil {
			err := plugin.HandlePluginCommand(pluginHandler, cmdPathPieces)
			if err != nil {
				fmt.Fprintf(rootCmd.OutOrStderr(), "Error: unknown command '%s' \nRun 'kn --help' for usage.\n", args[1])
				os.Exit(1)
			}
		} else if foundCmd.HasSubCommands() {
			if _, _, err := rootCmd.Find(innerArgs); err != nil {
				fmt.Fprintf(rootCmd.OutOrStderr(), showSubcommands(foundCmd, cmdPathPieces, innerArgs[0]))
				os.Exit(1)
			}
		}
	}

	return rootCmd
}

// NewKnCommand creates the rootCmd which is the base command when called without any subcommands
func NewKnCommand(params ...commands.KnParams) *cobra.Command {
	var p *commands.KnParams
	if len(params) == 0 {
		p = &commands.KnParams{}
	} else if len(params) == 1 {
		p = &params[0]
	} else {
		panic("Too many params objects to NewKnCommand")
	}
	p.Initialize()

	rootCmd := &cobra.Command{
		Use:   "kn",
		Short: "Knative client",
		Long: `Manage your Knative building blocks:

* Serving: Manage your services and release new software to them.
* Eventing: Manage event subscriptions and channels. Connect up event sources.`,

		// Disable docs header
		DisableAutoGenTag: true,

		// Affects children as well
		SilenceUsage: true,

		// Prevents Cobra from dealing with errors as we deal with them in main.go
		SilenceErrors: true,

		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			initConfigFlags()
			return flags.ReconcileBoolFlags(cmd.Flags())
		},
	}
	if p.Output != nil {
		rootCmd.SetOutput(p.Output)
	}

	// Persistent flags
	rootCmd.PersistentFlags().StringVar(&commands.CfgFile, "config", "", "kn config file (default is $HOME/.kn/config.yaml)")
	rootCmd.PersistentFlags().StringVar(&p.KubeCfgPath, "kubeconfig", "", "kubectl config file (default is $HOME/.kube/config)")
	flags.AddBothBoolFlags(rootCmd.PersistentFlags(), &p.LogHTTP, "log-http", "", false, "log http traffic")

	plugin.AddPluginFlags(rootCmd)
	plugin.BindPluginsFlagToViper(rootCmd)

	// root child commands
	rootCmd.AddCommand(service.NewServiceCommand(p))
	rootCmd.AddCommand(revision.NewRevisionCommand(p))
	rootCmd.AddCommand(plugin.NewPluginCommand(p))
	rootCmd.AddCommand(route.NewRouteCommand(p))
	rootCmd.AddCommand(completion.NewCompletionCommand(p))
	rootCmd.AddCommand(version.NewVersionCommand(p))
	rootCmd.AddCommand(source.NewSourceCommand(p))
	rootCmd.AddCommand(trigger.NewTriggerCommand(p))

	// Initialize default `help` cmd early to prevent unknown command errors
	rootCmd.InitDefaultHelpCmd()

	// Deal with empty and unknown sub command groups
	EmptyAndUnknownSubCommands(rootCmd)

	// Wrap usage.
	w, err := width()
	if err == nil {
		newUsage := strings.ReplaceAll(rootCmd.UsageTemplate(), "FlagUsages ",
			fmt.Sprintf("FlagUsagesWrapped %d ", w))
		rootCmd.SetUsageTemplate(newUsage)
	}

	// For glog parse error.
	flag.CommandLine.Parse([]string{})

	return rootCmd
}

// InitializeConfig initializes the kubeconfig used by all commands
func InitializeConfig() {
	cobra.OnInitialize(initConfig)
}

// EmptyAndUnknownSubCommands adds a RunE to all commands that are groups to
// deal with errors when called with empty or unknown sub command
func EmptyAndUnknownSubCommands(cmd *cobra.Command) {
	for _, childCmd := range cmd.Commands() {
		if childCmd.HasSubCommands() && childCmd.RunE == nil {
			childCmd.RunE = func(aCmd *cobra.Command, args []string) error {
				aCmd.Help()
				if len(args) == 0 {
					return fmt.Errorf("please provide a valid sub-command for \"kn %s\"", aCmd.Name())
				}
				return fmt.Errorf("unknown sub-command \"%s\" for \"kn %s\"", args[0], aCmd.Name())
			}
		}

		// recurse to deal with child commands that are themselves command groups
		EmptyAndUnknownSubCommands(childCmd)
	}
}

// Private

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if commands.CfgFile != "" {
		// Use config file from the flag.
		viper.SetConfigFile(commands.CfgFile)
	} else {
		// Find home directory.
		home, err := homedir.Dir()
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			os.Exit(1)
		}

		// Search config in home directory with name ".kn" (without extension)
		viper.AddConfigPath(path.Join(home, ".kn"))
		viper.SetConfigName("config")
	}

	viper.AutomaticEnv() // read in environment variables that match

	// If a config file is found, read it in.
	err := viper.ReadInConfig()
	if err == nil {
		fmt.Fprintln(os.Stderr, "Using kn config file:", viper.ConfigFileUsed())
	}
}

func initConfigFlags() {
	if viper.IsSet("plugins-dir") {
		commands.Cfg.PluginsDir = viper.GetString("plugins-dir")
	}

	// Always set the Cfg.LookupPlugins from viper value since default is false both ways
	var aBool bool
	aBool = viper.GetBool("lookup-plugins")
	commands.Cfg.LookupPlugins = &aBool
}

func extractKnPluginFlags(args []string) (string, bool, error) {
	pluginsDir := "~/.kn/plugins"
	lookupPluginsInPath := false

	dirFlag := "--plugins-dir"
	pathFlag := "--lookup-plugins"
	var err error

	for _, arg := range args {
		if arg == dirFlag {
			// They forgot the =...
			return "", false, fmt.Errorf("Missing %s flag value", dirFlag)
		} else if strings.HasPrefix(arg, dirFlag+"=") {
			// Starts with --plugins-dir=   so we parse the value
			pluginsDir = arg[len(dirFlag)+1:]
			if pluginsDir == "" {
				// They have a "=" but nothing afer it
				return "", false, fmt.Errorf("Missing %s flag value", dirFlag)
			}
		}

		if arg == pathFlag {
			// just --lookup-plugins   no "="
			lookupPluginsInPath = true
		} else if strings.HasPrefix(arg, pathFlag+"=") {
			// Starts with --lookup-plugins=  so we parse value
			arg = arg[len(pathFlag)+1:]
			if lookupPluginsInPath, err = strconv.ParseBool(arg); err != nil {
				return "", false, fmt.Errorf("Invalid boolean value(%q) for %s flag", arg, dirFlag)
			}
		}
	}
	return pluginsDir, lookupPluginsInPath, nil
}

func removeKnPluginFlags(args []string) []string {
	var remainingArgs []string

	// Remove these two flags from the list of args. Even though some of
	// of these cases should have resulted in an error, if for some reason
	// we got here just remove them anyway.
	for _, arg := range args {
		if arg == "--plugins-dir" ||
			strings.HasPrefix(arg, "--plugins-dir=") ||
			arg == "--lookup-plugins" ||
			strings.HasPrefix(arg, "--lookup-plugins=") {
			continue
		} else {
			remainingArgs = append(remainingArgs, arg)
		}
	}

	return remainingArgs
}

func width() (int, error) {
	width, _, err := terminal.GetSize(int(os.Stdout.Fd()))
	return width, err
}

func getCommands(args []string, innerArg string) string {
	commands := []string{"kn"}
	for _, arg := range args {
		if arg == innerArg {
			return strings.Join(commands, " ")
		}
		commands = append(commands, arg)
	}
	return ""
}

func showSubcommands(cmd *cobra.Command, args []string, innerArg string) string {
	var strs []string
	for _, subcmd := range cmd.Commands() {
		strs = append(strs, subcmd.Name())
	}
	return fmt.Sprintf("Error: unknown subcommand '%s' for '%s'. Available subcommands: %s\nRun 'kn --help' for usage.\n", innerArg, getCommands(args, innerArg), strings.Join(strs, ", "))
}
<|endoftext|>


<commit_before>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	"flag"
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	"strings"
	"time"
)

var conn dbox.IConnection
var count int

// var mwg sync.WaitGroup

var (
	t0                                time.Time
	custgroup, prodgroup, plcode, ref string
	value, fiscalyear                 int
	globalval                         float64
	mapkeysvalue                      map[string]float64
	masters                           toolkit.M
)

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}

func buildmap(holder interface{},
	fnModel func() orm.IModel,
	filter *dbox.Filter,
	fnIter func(holder interface{}, obj interface{})) interface{} {
	crx, _ := gdrj.Find(fnModel(), filter, nil)
	defer crx.Close()
	for {
		s := fnModel()
		e := crx.Fetch(s, 1, false)
		if e != nil {
			break
		}
		fnIter(holder, s)
	}
	return holder
}

func prepmaster() {
	masters = toolkit.M{}
	masters.Set("plmodel", buildmap(map[string]*gdrj.PLModel{},
		func() orm.IModel {
			return new(gdrj.PLModel)
		},
		nil,
		func(holder, obj interface{}) {
			h := holder.(map[string]*gdrj.PLModel)
			o := obj.(*gdrj.PLModel)
			h[o.ID] = o
		}).(map[string]*gdrj.PLModel))
}

func main() {
	t0 = time.Now()
	mapkeysvalue = make(map[string]float64)

	flag.IntVar(&value, "value", 0, "representation of value need to be allocation. Default is 0")
	//branch,channel,group
	flag.StringVar(&custgroup, "custgroup", "global", "group of customer. Default is global")
	//brand,group
	flag.StringVar(&prodgroup, "prodgroup", "global", "group of product. Default is global")
	flag.IntVar(&fiscalyear, "year", 2015, "YYYY representation of godrej fiscal year. Default is 2015")
	flag.StringVar(&plcode, "plcode", "", "PL Code to take the value. Default is blank")
	flag.StringVar(&ref, "ref", "", "Reference from document or other. Default is blank")
	flag.Parse()

	eperiode := time.Date(fiscalyear, 4, 1, 0, 0, 0, 0, time.UTC)
	speriode := eperiode.AddDate(-1, 0, 0)

	filter := dbox.And(dbox.Gte("date.date", speriode), dbox.Lt("date.date", eperiode))

	if plcode == "" || value == 0 {
		toolkit.Println("PLCode and Value are mandatory to fill")
		os.Exit(1)
	}

	setinitialconnection()
	defer gdrj.CloseDb()

	toolkit.Println("Get Data Master...")
	prepmaster()

	toolkit.Println("Start Data Process...")
	c, _ := gdrj.Find(new(gdrj.SalesPL), filter, nil)
	defer c.Close()

	splcount := c.Count()
	step := splcount / 100
	i := 0

	for {
		i++

		spl := new(gdrj.SalesPL)
		e := c.Fetch(spl, 1, false)
		if e != nil {
			break
		}
		key := toolkit.Sprintf("%v_%v", spl.Date.Month, spl.Date.Year)

		switch custgroup {
		case "branch":
			key = toolkit.Sprintf("%v_%v", key, spl.Customer.BranchID)
		case "channel":
			key = toolkit.Sprintf("%v_%v", key, spl.Customer.ChannelID)
		case "group":
			key = toolkit.Sprintf("%v_%v", key, spl.Customer.CustomerGroup)
		default:
			key = toolkit.Sprintf("%v_", key)
		}

		switch prodgroup {
		case "brand":
			key = toolkit.Sprintf("%v_%v", key, spl.Product.Brand)
		case "group":
			key = toolkit.Sprintf("%v_%v", key, spl.Product.BrandCategoryID)
		default:
			key = toolkit.Sprintf("%v_", key)
		}

		mapkeysvalue[key] += spl.GrossAmount
		globalval += spl.GrossAmount

		if i > step {
			step += splcount / 100
			toolkit.Printfn("Processing %d of %d in %s", i, splcount,
				time.Since(t0).String())
		}

	}

	toolkit.Printfn("Preparing the data")
	mcount := len(mapkeysvalue)
	i = 0
	for k, v := range mapkeysvalue {
		i++

		akey := strings.Split(k, "_")
		tcustomer := new(gdrj.Customer)
		tproduct := new(gdrj.Product)

		if len(akey) > 2 && akey[2] != "" {
			switch custgroup {
			case "branch":
				tcustomer.BranchID = akey[2]
			case "channel":
				tcustomer.ChannelID = akey[2]
			case "group":
				tcustomer.CustomerGroup = akey[2]
			}
		}

		if len(akey) > 3 && akey[3] != "" {
			switch prodgroup {
			case "brand":
				tproduct.Brand = akey[3]
			case "group":
				tproduct.BrandCategoryID = akey[3]
			}
		}

		spl := new(gdrj.SalesPL)
		spl.ID = toolkit.Sprintf("%v%v%v%v", akey[0], akey[1], "", "")
		spl.Date = gdrj.SetDate(time.Date(toolkit.ToInt(akey[0], toolkit.RoundingAuto),
			time.Month(toolkit.ToInt(akey[1], toolkit.RoundingAuto)),
			1, 0, 0, 0, 0, time.UTC))
		spl.Customer = tcustomer
		spl.Product = tproduct
		spl.Source = "ADJUST"
		spl.Ref = ref

		spl.PC = new(gdrj.ProfitCenter)
		spl.CC = new(gdrj.CostCenter)

		amount := toolkit.ToFloat64(value, 6, toolkit.RoundingAuto) * (v / globalval)
		_ = amount
		plmodels := masters.Get("plmodel").(map[string]*gdrj.PLModel)
		spl.AddData(plcode, amount, plmodels)
		spl.CalcSum(masters)

		toolkit.Println(spl.ID)
		gdrj.Save(spl)

		toolkit.Printfn("Saving %d of %d in %s", i, mcount,
			time.Since(t0).String())
	}

	toolkit.Printfn("Processing done in %s",
		time.Since(t0).String())
}
<commit_msg>allocation<commit_after>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	"flag"
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	"strings"
	"time"
)

var conn dbox.IConnection
var count int

// var mwg sync.WaitGroup

var (
	t0                                time.Time
	custgroup, prodgroup, plcode, ref string
	value, fiscalyear                 int
	globalval                         float64
	mapkeysvalue                      map[string]float64
	masters                           toolkit.M
)

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}

func buildmap(holder interface{},
	fnModel func() orm.IModel,
	filter *dbox.Filter,
	fnIter func(holder interface{}, obj interface{})) interface{} {
	crx, _ := gdrj.Find(fnModel(), filter, nil)
	defer crx.Close()
	for {
		s := fnModel()
		e := crx.Fetch(s, 1, false)
		if e != nil {
			break
		}
		fnIter(holder, s)
	}
	return holder
}

func prepmaster() {
	masters = toolkit.M{}
	masters.Set("plmodel", buildmap(map[string]*gdrj.PLModel{},
		func() orm.IModel {
			return new(gdrj.PLModel)
		},
		nil,
		func(holder, obj interface{}) {
			h := holder.(map[string]*gdrj.PLModel)
			o := obj.(*gdrj.PLModel)
			h[o.ID] = o
		}).(map[string]*gdrj.PLModel))
}

func main() {
	t0 = time.Now()
	mapkeysvalue = make(map[string]float64)

	flag.IntVar(&value, "value", 0, "representation of value need to be allocation. Default is 0")
	//branch,channel,group
	flag.StringVar(&custgroup, "custgroup", "global", "group of customer. Default is global")
	//brand,group
	flag.StringVar(&prodgroup, "prodgroup", "global", "group of product. Default is global")
	flag.IntVar(&fiscalyear, "year", 2015, "YYYY representation of godrej fiscal year. Default is 2015")
	flag.StringVar(&plcode, "plcode", "", "PL Code to take the value. Default is blank")
	flag.StringVar(&ref, "ref", "", "Reference from document or other. Default is blank")
	flag.Parse()

	eperiode := time.Date(fiscalyear, 4, 1, 0, 0, 0, 0, time.UTC)
	speriode := eperiode.AddDate(-1, 0, 0)

	filter := dbox.And(dbox.Gte("date.date", speriode), dbox.Lt("date.date", eperiode))

	if plcode == "" || value == 0 {
		toolkit.Println("PLCode and Value are mandatory to fill")
		os.Exit(1)
	}

	setinitialconnection()
	defer gdrj.CloseDb()

	toolkit.Println("Get Data Master...")
	prepmaster()

	toolkit.Println("Start Data Process...")
	c, _ := gdrj.Find(new(gdrj.SalesPL), filter, nil)
	defer c.Close()

	splcount := c.Count()
	step := splcount / 100
	i := 0

	for {
		i++

		spl := new(gdrj.SalesPL)
		e := c.Fetch(spl, 1, false)
		if e != nil {
			break
		}
		key := toolkit.Sprintf("%d_%d", spl.Date.Month, spl.Date.Year)

		switch custgroup {
		case "branch":
			key = toolkit.Sprintf("%v_%v", key, spl.Customer.BranchID)
		case "channel":
			key = toolkit.Sprintf("%v_%v", key, spl.Customer.ChannelID)
		case "group":
			key = toolkit.Sprintf("%v_%v", key, spl.Customer.CustomerGroup)
		default:
			key = toolkit.Sprintf("%v_", key)
		}

		switch prodgroup {
		case "brand":
			key = toolkit.Sprintf("%v_%v", key, spl.Product.Brand)
		case "group":
			key = toolkit.Sprintf("%v_%v", key, spl.Product.BrandCategoryID)
		default:
			key = toolkit.Sprintf("%v_", key)
		}

		mapkeysvalue[key] += spl.GrossAmount
		globalval += spl.GrossAmount

		if i > step {
			step += splcount / 100
			toolkit.Printfn("Processing %d of %d in %s", i, splcount,
				time.Since(t0).String())
		}

	}

	toolkit.Printfn("Preparing the data")
	mcount := len(mapkeysvalue)
	i = 0
	for k, v := range mapkeysvalue {
		i++

		akey := strings.Split(k, "_")
		tcustomer := new(gdrj.Customer)
		tproduct := new(gdrj.Product)

		if len(akey) > 2 && akey[2] != "" {
			switch custgroup {
			case "branch":
				tcustomer.BranchID = akey[2]
			case "channel":
				tcustomer.ChannelID = akey[2]
			case "group":
				tcustomer.CustomerGroup = akey[2]
			}
		}

		if len(akey) > 3 && akey[3] != "" {
			switch prodgroup {
			case "brand":
				tproduct.Brand = akey[3]
			case "group":
				tproduct.BrandCategoryID = akey[3]
			}
		}

		spl := new(gdrj.SalesPL)
		spl.ID = toolkit.Sprintf("%v%v%v%v", akey[0], akey[1], "", "")
		spl.Date = gdrj.SetDate(time.Date(toolkit.ToInt(akey[1], toolkit.RoundingAuto),
			time.Month(toolkit.ToInt(akey[0], toolkit.RoundingAuto)),
			1, 0, 0, 0, 0, time.UTC))
		spl.Customer = tcustomer
		spl.Product = tproduct
		spl.Source = "ADJUST"
		spl.Ref = ref

		spl.PC = new(gdrj.ProfitCenter)
		spl.CC = new(gdrj.CostCenter)

		amount := toolkit.ToFloat64(value, 6, toolkit.RoundingAuto) * (v / globalval)
		_ = amount
		plmodels := masters.Get("plmodel").(map[string]*gdrj.PLModel)
		spl.AddData(plcode, amount, plmodels)
		spl.CalcSum(masters)

		gdrj.Save(spl)

		toolkit.Printfn("Saving %d of %d in %s", i, mcount,
			time.Since(t0).String())
	}

	toolkit.Printfn("Processing done in %s",
		time.Since(t0).String())
}
<|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 markmaster

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientset "k8s.io/client-go/kubernetes"
	restclient "k8s.io/client-go/rest"
	kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
	kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
	"k8s.io/kubernetes/pkg/util/node"
)

func TestMarkMaster(t *testing.T) {
	// Note: this test takes advantage of the deterministic marshalling of
	// JSON provided by strategicpatch so that "expectedPatch" can use a
	// string equality test instead of a logical JSON equality test. That
	// will need to change if strategicpatch's behavior changes in the
	// future.
	tests := []struct {
		name           string
		existingLabel  string
		existingTaints []v1.Taint
		newTaints      []v1.Taint
		expectedPatch  string
	}{
		{
			"master label and taint missing",
			"",
			nil,
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}},\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}",
		},
		{
			"master label and taint missing but taint not wanted",
			"",
			nil,
			nil,
			"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}",
		},
		{
			"master label missing",
			"",
			[]v1.Taint{kubeadmconstants.MasterTaint},
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}",
		},
		{
			"master taint missing",
			kubeadmconstants.LabelNodeRoleMaster,
			nil,
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}",
		},
		{
			"nothing missing",
			kubeadmconstants.LabelNodeRoleMaster,
			[]v1.Taint{kubeadmconstants.MasterTaint},
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{}",
		},
		{
			"nothing missing but taint unwanted",
			kubeadmconstants.LabelNodeRoleMaster,
			[]v1.Taint{kubeadmconstants.MasterTaint},
			nil,
			"{\"spec\":{\"taints\":null}}",
		},
	}

	for _, tc := range tests {
		hostname := node.GetHostname("")
		masterNode := &v1.Node{
			ObjectMeta: metav1.ObjectMeta{
				Name: hostname,
				Labels: map[string]string{
					kubeletapis.LabelHostname: hostname,
				},
			},
		}

		if tc.existingLabel != "" {
			masterNode.ObjectMeta.Labels[tc.existingLabel] = ""
		}

		if tc.existingTaints != nil {
			masterNode.Spec.Taints = tc.existingTaints
		}

		jsonNode, err := json.Marshal(masterNode)
		if err != nil {
			t.Fatalf("MarkMaster(%s): unexpected encoding error: %v", tc.name, err)
		}

		var patchRequest string
		s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			w.Header().Set("Content-Type", "application/json")

			if req.URL.Path != "/api/v1/nodes/"+hostname {
				t.Errorf("MarkMaster(%s): request for unexpected HTTP resource: %v", tc.name, req.URL.Path)
				w.WriteHeader(http.StatusNotFound)
				return
			}

			switch req.Method {
			case "GET":
			case "PATCH":
				patchRequest = toString(req.Body)
			default:
				t.Errorf("MarkMaster(%s): request for unexpected HTTP verb: %v", tc.name, req.Method)
				w.WriteHeader(http.StatusNotFound)
				return
			}

			w.WriteHeader(http.StatusOK)
			w.Write(jsonNode)
		}))
		defer s.Close()

		cs, err := clientset.NewForConfig(&restclient.Config{Host: s.URL})
		if err != nil {
			t.Fatalf("MarkMaster(%s): unexpected error building clientset: %v", tc.name, err)
		}

		if err := MarkMaster(cs, hostname, tc.newTaints); err != nil {
			t.Errorf("MarkMaster(%s) returned unexpected error: %v", tc.name, err)
		}

		if tc.expectedPatch != patchRequest {
			t.Errorf("MarkMaster(%s) wanted patch %v, got %v", tc.name, tc.expectedPatch, patchRequest)
		}
	}
}

func toString(r io.Reader) string {
	buf := new(bytes.Buffer)
	buf.ReadFrom(r)
	return buf.String()
}
<commit_msg>Update tests to reflect that kubeadm taints should not override node taints<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 markmaster

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientset "k8s.io/client-go/kubernetes"
	restclient "k8s.io/client-go/rest"
	kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
	kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
	"k8s.io/kubernetes/pkg/util/node"
)

func TestMarkMaster(t *testing.T) {
	// Note: this test takes advantage of the deterministic marshalling of
	// JSON provided by strategicpatch so that "expectedPatch" can use a
	// string equality test instead of a logical JSON equality test. That
	// will need to change if strategicpatch's behavior changes in the
	// future.
	tests := []struct {
		name           string
		existingLabel  string
		existingTaints []v1.Taint
		newTaints      []v1.Taint
		expectedPatch  string
	}{
		{
			"master label and taint missing",
			"",
			nil,
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}},\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}",
		},
		{
			"master label and taint missing but taint not wanted",
			"",
			nil,
			nil,
			"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}",
		},
		{
			"master label missing",
			"",
			[]v1.Taint{kubeadmconstants.MasterTaint},
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}",
		},
		{
			"master taint missing",
			kubeadmconstants.LabelNodeRoleMaster,
			nil,
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}",
		},
		{
			"nothing missing",
			kubeadmconstants.LabelNodeRoleMaster,
			[]v1.Taint{kubeadmconstants.MasterTaint},
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{}",
		},
		{
			"has taint and no new taints wanted",
			kubeadmconstants.LabelNodeRoleMaster,
			[]v1.Taint{
				{
					Key:    "node.cloudprovider.kubernetes.io/uninitialized",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			nil,
			"{}",
		},
		{
			"has taint and should merge with wanted taint",
			kubeadmconstants.LabelNodeRoleMaster,
			[]v1.Taint{
				{
					Key:    "node.cloudprovider.kubernetes.io/uninitialized",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			[]v1.Taint{kubeadmconstants.MasterTaint},
			"{\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"},{\"effect\":\"NoSchedule\",\"key\":\"node.cloudprovider.kubernetes.io/uninitialized\"}]}}",
		},
	}

	for _, tc := range tests {
		hostname := node.GetHostname("")
		masterNode := &v1.Node{
			ObjectMeta: metav1.ObjectMeta{
				Name: hostname,
				Labels: map[string]string{
					kubeletapis.LabelHostname: hostname,
				},
			},
		}

		if tc.existingLabel != "" {
			masterNode.ObjectMeta.Labels[tc.existingLabel] = ""
		}

		if tc.existingTaints != nil {
			masterNode.Spec.Taints = tc.existingTaints
		}

		jsonNode, err := json.Marshal(masterNode)
		if err != nil {
			t.Fatalf("MarkMaster(%s): unexpected encoding error: %v", tc.name, err)
		}

		var patchRequest string
		s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			w.Header().Set("Content-Type", "application/json")

			if req.URL.Path != "/api/v1/nodes/"+hostname {
				t.Errorf("MarkMaster(%s): request for unexpected HTTP resource: %v", tc.name, req.URL.Path)
				w.WriteHeader(http.StatusNotFound)
				return
			}

			switch req.Method {
			case "GET":
			case "PATCH":
				patchRequest = toString(req.Body)
			default:
				t.Errorf("MarkMaster(%s): request for unexpected HTTP verb: %v", tc.name, req.Method)
				w.WriteHeader(http.StatusNotFound)
				return
			}

			w.WriteHeader(http.StatusOK)
			w.Write(jsonNode)
		}))
		defer s.Close()

		cs, err := clientset.NewForConfig(&restclient.Config{Host: s.URL})
		if err != nil {
			t.Fatalf("MarkMaster(%s): unexpected error building clientset: %v", tc.name, err)
		}

		if err := MarkMaster(cs, hostname, tc.newTaints); err != nil {
			t.Errorf("MarkMaster(%s) returned unexpected error: %v", tc.name, err)
		}

		if tc.expectedPatch != patchRequest {
			t.Errorf("MarkMaster(%s) wanted patch %v, got %v", tc.name, tc.expectedPatch, patchRequest)
		}
	}
}

func toString(r io.Reader) string {
	buf := new(bytes.Buffer)
	buf.ReadFrom(r)
	return buf.String()
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"go/build"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var archMap = map[string]string{
	"cortexm0":  "-mcpu=cortex-m0 -mthumb -mfloat-abi=soft",
	"cortexm3":  "-mcpu=cortex-m3 -mthumb -mfloat-abi=soft",
	"cortexm4":  "-mcpu=cortex-m4 -mthumb -mfloat-abi=soft",
	"cortexm4f": "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16",
}

var osMap = map[string]struct{ cc, ld string }{
	"noos": {
		cc: "-ffreestanding -nostdinc -fno-exceptions -nostartfiles",
		ld: "-nostdlib  -nodefaultlibs  -nostartfiles",
	},
}

type CFLAGS struct {
	Arch string // architecture flags
	OS   string // OS related flags
	Dbg  string // debuging flags
	Opt  string // optimization flags
	Warn string // warning flags
	Incl string // -I flags
}

func (cf *CFLAGS) SplitAll() []string {
	var f []string
	f = append(f, strings.Fields(cf.Arch)...)
	f = append(f, strings.Fields(cf.OS)...)
	f = append(f, strings.Fields(cf.Dbg)...)
	f = append(f, strings.Fields(cf.Opt)...)
	f = append(f, strings.Fields(cf.Warn)...)
	f = append(f, strings.Fields(cf.Incl)...)
	return f
}

type LDFLAGS struct {
	OS     string // OS related flags
	Incl   string // -L flags
	Script string // path to linker script or empty if default script
	Opt    string // optimization flags
}

func (lf *LDFLAGS) SplitAll() []string {
	var f []string
	f = append(f, strings.Fields(lf.OS)...)
	f = append(f, strings.Fields(lf.Opt)...)
	f = append(f, strings.Fields(lf.Incl)...)
	if lf.Script != "" {
		f = append(f, "-T", lf.Script)
	}
	return f
}

type BuildTools struct {
	CC     string // path to the C compiler
	CFLAGS []string

	LD      string // path to the linker
	LDFLAGS []string

	AR      string // path to the archiver
	ARFLAGS []string

	Log io.Writer

	importPaths []string
}

const EGLDSCRIPT = "script.ld"

func NewBuildTools(ctx *build.Context) (*BuildTools, error) {
	cflags := CFLAGS{
		Dbg:  "-g",
		Opt:  "-O" + optLevel + " -fplan9-extensions -fno-delete-null-pointer-checks -fno-common -freg-struct-return -ffunction-sections",
		Warn: "-Wall -Wno-parentheses -Wno-unused-function -Wno-unused-variable -Wno-unused-label -Wno-maybe-uninitialized",
		Incl: "-I" + filepath.Join(ctx.GOROOT, "src"),
	}
	ldflags := LDFLAGS{
		Script: EGLDSCRIPT,
		Incl:   "-L" + filepath.Join(ctx.GOROOT, "ld"),
		Opt:    "-gc-sections",
	}

	if fl, ok := archMap[ctx.GOARCH]; ok {
		cflags.Arch = fl
	} else {
		return nil, errors.New("unknown EGARCH: " + ctx.GOARCH)
	}
	if fl, ok := osMap[ctx.GOOS]; ok {
		cflags.OS = fl.cc
		ldflags.OS = fl.ld
	} else {
		return nil, errors.New("unknown EGOS: " + ctx.GOOS)
	}

	pkgoa := filepath.Join("pkg", ctx.GOOS+"_"+ctx.GOARCH)
	importPaths := append([]string{ctx.GOROOT}, strings.Split(ctx.GOPATH, ":")...)
	for i, p := range importPaths {
		ldflags.Incl += " -L" + filepath.Join(p, "ld")
		p = filepath.Join(p, pkgoa)
		cflags.Incl += " -I" + p
		importPaths[i] = p
	}

	bt := &BuildTools{
		CC:      EGCC,
		CFLAGS:  cflags.SplitAll(),
		LD:      EGLD,
		LDFLAGS: ldflags.SplitAll(),
		AR:      EGAR,
		ARFLAGS: []string{"rcs"},

		importPaths: importPaths,
	}
	return bt, nil
}

func (bt *BuildTools) logCmd(cmd string, args []string) {
	if bt.Log == nil {
		return
	}
	io.WriteString(bt.Log, cmd)
	for _, a := range args {
		io.WriteString(bt.Log, " "+a)
	}
	bt.Log.Write([]byte{'\n'})
}

func (bt *BuildTools) Compile(o, c string) error {
	args := append(bt.CFLAGS)
	if odir := filepath.Dir(o); filepath.Base(odir) == "main" {
		args = append(args, "-I", odir)
	}
	args = append(args, "-o", o, "-c", c)

	bt.logCmd(bt.CC, args)

	cmd := exec.Command(bt.CC, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func (bt *BuildTools) Archive(a string, f ...string) error {
	os.Remove(a)

	args := append(bt.ARFLAGS, a)
	args = append(args, f...)

	bt.logCmd(bt.AR, args)

	cmd := exec.Command(bt.AR, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func (bt *BuildTools) getImports(known map[string]struct{}, add []string) ([]string, error) {
	var a []string

	for _, ppath := range add {
		if _, ok := known[ppath]; ok {
			continue
		}
		var (
			apath string
			data  []byte
			err   error
		)
		for _, ipath := range bt.importPaths {
			apath = filepath.Join(ipath, ppath+".a")
			data, err = arReadFile(apath, "__.IMPORTS")
			if err == nil {
				break
			}
			if !os.IsNotExist(err) {
				return nil, err
			}
			apath = ""
		}
		if apath == "" {
			return nil, errors.New("can't find compiled package for " + ppath)
		}
		known[apath] = struct{}{}
		a = append(a, apath)
		ia, err := bt.getImports(known, strings.Fields(string(data)))
		if err != nil {
			return nil, err
		}
		a = append(a, ia...)
	}
	return a, nil
}

func (bt *BuildTools) Link(e string, imports []string, o ...string) error {
	args := append(bt.LDFLAGS, "-o", e)
	args = append(args, o...)

	// Find all imported packages with all nested imports
	a, err := bt.getImports(make(map[string]struct{}), imports)
	if err != nil {
		return err
	}
	args = append(args, a...)

	bt.logCmd(bt.LD, args)

	cmd := exec.Command(bt.LD, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<commit_msg>Allow link with libgcc<commit_after>package main

import (
	"errors"
	"go/build"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var archMap = map[string]string{
	"cortexm0":  "-mcpu=cortex-m0 -mthumb -mfloat-abi=soft",
	"cortexm3":  "-mcpu=cortex-m3 -mthumb -mfloat-abi=soft",
	"cortexm4":  "-mcpu=cortex-m4 -mthumb -mfloat-abi=soft",
	"cortexm4f": "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16",
}

var osMap = map[string]struct{ cc, ld string }{
	"noos": {
		cc: "-ffreestanding -nostdinc -fno-exceptions -nostartfiles",
		ld: "-nostdlib  -nodefaultlibs  -nostartfiles -lgcc",
	},
}

type CFLAGS struct {
	Arch string // architecture flags
	OS   string // OS related flags
	Dbg  string // debuging flags
	Opt  string // optimization flags
	Warn string // warning flags
	Incl string // -I flags
}

func (cf *CFLAGS) SplitAll() []string {
	var f []string
	f = append(f, strings.Fields(cf.Arch)...)
	f = append(f, strings.Fields(cf.OS)...)
	f = append(f, strings.Fields(cf.Dbg)...)
	f = append(f, strings.Fields(cf.Opt)...)
	f = append(f, strings.Fields(cf.Warn)...)
	f = append(f, strings.Fields(cf.Incl)...)
	return f
}

type LDFLAGS struct {
	OS     string // OS related flags
	Incl   string // -L flags
	Script string // Path to linker script or empty if default script
	Opt    string // Optimization flags
}

func (lf *LDFLAGS) SplitAll() []string {
	var f []string
	f = append(f, strings.Fields(lf.OS)...)
	f = append(f, strings.Fields(lf.Opt)...)
	f = append(f, strings.Fields(lf.Incl)...)
	if lf.Script != "" {
		f = append(f, "-T", lf.Script)
	}
	return f
}

type BuildTools struct {
	CC     string // path to the C compiler
	CFLAGS []string

	LD       string // path to the linker
	LDFLAGS  []string
	LDlibgcc string

	AR      string // path to the archiver
	ARFLAGS []string

	Log io.Writer

	importPaths []string
}

const EGLDSCRIPT = "script.ld"

func NewBuildTools(ctx *build.Context) (*BuildTools, error) {
	cflags := CFLAGS{
		Dbg:  "-g",
		Opt:  "-O" + optLevel + " -fplan9-extensions -fno-delete-null-pointer-checks -fno-common -freg-struct-return -ffunction-sections",
		Warn: "-Wall -Wno-parentheses -Wno-unused-function -Wno-unused-variable -Wno-unused-label -Wno-maybe-uninitialized",
		Incl: "-I" + filepath.Join(ctx.GOROOT, "src"),
	}
	if fl, ok := archMap[ctx.GOARCH]; ok {
		cflags.Arch = fl
	} else {
		return nil, errors.New("unknown EGARCH: " + ctx.GOARCH)
	}

	ldflags := LDFLAGS{
		Script: EGLDSCRIPT,
		Incl:   "-L" + filepath.Join(ctx.GOROOT, "ld"),
		Opt:    "-gc-sections",
	}

	if fl, ok := osMap[ctx.GOOS]; ok {
		cflags.OS = fl.cc
		ldflags.OS = fl.ld
	} else {
		return nil, errors.New("unknown EGOS: " + ctx.GOOS)
	}

	pkgoa := filepath.Join("pkg", ctx.GOOS+"_"+ctx.GOARCH)
	importPaths := append([]string{ctx.GOROOT}, strings.Split(ctx.GOPATH, ":")...)
	for i, p := range importPaths {
		ldflags.Incl += " -L" + filepath.Join(p, "ld")
		p = filepath.Join(p, pkgoa)
		cflags.Incl += " -I" + p
		importPaths[i] = p
	}

	bt := &BuildTools{
		CC:      EGCC,
		CFLAGS:  cflags.SplitAll(),
		LD:      EGLD,
		LDFLAGS: ldflags.SplitAll(),
		AR:      EGAR,
		ARFLAGS: []string{"rcs"},

		importPaths: importPaths,
	}

	for i, f := range bt.LDFLAGS {
		if f == "-lgcc" {
			libgcc, err := exec.Command(
				EGCC,
				append(strings.Fields(cflags.Arch), "-print-libgcc-file-name")...,
			).Output()
			if err != nil {
				return nil, err
			}
			bt.LDFLAGS = append(bt.LDFLAGS[:i], bt.LDFLAGS[i+1:]...)
			bt.LDlibgcc = strings.TrimSpace(string(libgcc))
			break
		}
	}

	return bt, nil
}

func (bt *BuildTools) logCmd(cmd string, args []string) {
	if bt.Log == nil {
		return
	}
	io.WriteString(bt.Log, cmd)
	for _, a := range args {
		io.WriteString(bt.Log, " "+a)
	}
	bt.Log.Write([]byte{'\n'})
}

func (bt *BuildTools) Compile(o, c string) error {
	args := bt.CFLAGS
	if odir := filepath.Dir(o); filepath.Base(odir) == "main" {
		args = append(args, "-I", odir)
	}
	args = append(args, "-o", o, "-c", c)

	bt.logCmd(bt.CC, args)

	cmd := exec.Command(bt.CC, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func (bt *BuildTools) Archive(a string, f ...string) error {
	os.Remove(a)

	args := append(bt.ARFLAGS, a)
	args = append(args, f...)

	bt.logCmd(bt.AR, args)

	cmd := exec.Command(bt.AR, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func (bt *BuildTools) getImports(known map[string]struct{}, add []string) ([]string, error) {
	var a []string

	for _, ppath := range add {
		if _, ok := known[ppath]; ok {
			continue
		}
		var (
			apath string
			data  []byte
			err   error
		)
		for _, ipath := range bt.importPaths {
			apath = filepath.Join(ipath, ppath+".a")
			data, err = arReadFile(apath, "__.IMPORTS")
			if err == nil {
				break
			}
			if !os.IsNotExist(err) {
				return nil, err
			}
			apath = ""
		}
		if apath == "" {
			return nil, errors.New("can't find compiled package for " + ppath)
		}
		known[apath] = struct{}{}
		a = append(a, apath)
		ia, err := bt.getImports(known, strings.Fields(string(data)))
		if err != nil {
			return nil, err
		}
		a = append(a, ia...)
	}
	return a, nil
}

func (bt *BuildTools) Link(e string, imports []string, o ...string) error {
	args := append(bt.LDFLAGS, "-o", e)
	args = append(args, o...)

	// Find all imported packages with all nested imports
	a, err := bt.getImports(make(map[string]struct{}), imports)
	if err != nil {
		return err
	}
	args = append(args, a...)

	if bt.LDlibgcc != "" {
		// Ugly trick to insert libgcc.a before last builtin.a.
		lasta := len(args) - 1
		args = append(args[:lasta], bt.LDlibgcc, args[lasta])
	}

	bt.logCmd(bt.LD, args)

	cmd := exec.Command(bt.LD, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<|endoftext|>


<commit_before>/*
Copyright 2014 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 version

// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the Kubernetes
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// If you are looking at these fields in the git tree, they look
// strange. They are modified on the fly by the build process. The
// in-tree values are dummy values used for "git archive", which also
// works for GitHub tar downloads.
//
// When releasing a new Kubernetes version, this file is updated by
// build/mark_new_version.sh to reflect the new version, and then a
// git annotated tag (using format vX.Y where X == Major version and Y
// == Minor version) is created to point to the commit that updates
// pkg/version/base.go
var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion
	// instead. First step in deprecation, keep the fields but make
	// them irrelevant. (Next we'll take it out, which may muck with
	// scripts consuming the kubectl version output - but most of
	// these should be looking at gitVersion already anyways.)
	gitMajor string = "1"  // major version, always numeric
	gitMinor string = "4+" // minor version, numeric possibly followed by "+"

	// semantic version, derived by build scripts (see
	// https://github.com/kubernetes/kubernetes/blob/master/docs/design/versioning.md
	// for a detailed discussion of this field)
	//
	// TODO: This field is still called "gitVersion" for legacy
	// reasons. For prerelease versions, the build metadata on the
	// semantic version is a git hash, but the version itself is no
	// longer the direct output of "git describe", but a slight
	// translation to be semver compliant.
	gitVersion   string = "v1.4.0-beta.9+$Format:%h$"
	gitCommit    string = "$Format:%H$"    // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"

	buildDate string = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ')
)
<commit_msg>Kubernetes version v1.4.0-beta.10<commit_after>/*
Copyright 2014 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 version

// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the Kubernetes
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// If you are looking at these fields in the git tree, they look
// strange. They are modified on the fly by the build process. The
// in-tree values are dummy values used for "git archive", which also
// works for GitHub tar downloads.
//
// When releasing a new Kubernetes version, this file is updated by
// build/mark_new_version.sh to reflect the new version, and then a
// git annotated tag (using format vX.Y where X == Major version and Y
// == Minor version) is created to point to the commit that updates
// pkg/version/base.go
var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion
	// instead. First step in deprecation, keep the fields but make
	// them irrelevant. (Next we'll take it out, which may muck with
	// scripts consuming the kubectl version output - but most of
	// these should be looking at gitVersion already anyways.)
	gitMajor string = "1"  // major version, always numeric
	gitMinor string = "4+" // minor version, numeric possibly followed by "+"

	// semantic version, derived by build scripts (see
	// https://github.com/kubernetes/kubernetes/blob/master/docs/design/versioning.md
	// for a detailed discussion of this field)
	//
	// TODO: This field is still called "gitVersion" for legacy
	// reasons. For prerelease versions, the build metadata on the
	// semantic version is a git hash, but the version itself is no
	// longer the direct output of "git describe", but a slight
	// translation to be semver compliant.
	gitVersion   string = "v1.4.0-beta.10+$Format:%h$"
	gitCommit    string = "$Format:%H$"    // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"

	buildDate string = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ')
)
<|endoftext|>