<commit_before>package alerts

import (
	"context"
	"fmt"
	"strings"
	"time"

	o "github.com/onsi/gomega"
	configclient "github.com/openshift/client-go/config/clientset/versioned"
	"github.com/openshift/origin/pkg/synthetictests/allowedalerts"
	testresult "github.com/openshift/origin/pkg/test/ginkgo/result"
	"github.com/openshift/origin/test/extended/util/disruption"
	helper "github.com/openshift/origin/test/extended/util/prometheus"
	prometheusv1 "github.com/prometheus/client_golang/api/prometheus/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kubernetes/test/e2e/framework"
)

type allowedAlertsFunc func(configclient.Interface) (allowedFiringWithBugs, allowedFiring, allowedPendingWithBugs, allowedPending helper.MetricConditions)

// CheckAlerts will query prometheus and ensure no-unexpected alerts were pending or firing.
// Used both post-upgrade and post-conformance, with different allowances for each.
func CheckAlerts(allowancesFunc allowedAlertsFunc, prometheusClient prometheusv1.API, configClient configclient.Interface, testDuration time.Duration, f *framework.Framework) {
	firingAlertsWithBugs, allowedFiringAlerts, pendingAlertsWithBugs, allowedPendingAlerts :=
		allowancesFunc(configClient)

	// we exclude alerts that have their own separate tests.
	for _, alertTest := range allowedalerts.AllAlertTests(context.TODO(), nil, 0) {
		switch alertTest.AlertState() {
		case allowedalerts.AlertPending:
			// a pending test covers pending and everything above (firing)
			allowedPendingAlerts = append(allowedPendingAlerts,
				helper.MetricCondition{
					Selector: map[string]string{"alertname": alertTest.AlertName()},
					Text:     "has a separate e2e test",
				},
			)
			allowedFiringAlerts = append(allowedFiringAlerts,
				helper.MetricCondition{
					Selector: map[string]string{"alertname": alertTest.AlertName()},
					Text:     "has a separate e2e test",
				},
			)
		case allowedalerts.AlertInfo:
			// an info test covers all firing
			allowedFiringAlerts = append(allowedFiringAlerts,
				helper.MetricCondition{
					Selector: map[string]string{"alertname": alertTest.AlertName()},
					Text:     "has a separate e2e test",
				},
			)
		}
	}

	knownViolations := sets.NewString()
	unexpectedViolations := sets.NewString()
	unexpectedViolationsAsFlakes := sets.NewString()
	debug := sets.NewString()

	// Invariant: No non-info level alerts should have fired
	firingAlertQuery := fmt.Sprintf(`
sort_desc(
count_over_time(ALERTS{alertstate="firing",severity!="info",alertname!~"Watchdog|AlertmanagerReceiversNotConfigured"}[%[1]s:1s])
) > 0
`, testDuration)
	result, err := helper.RunQuery(context.TODO(), prometheusClient, firingAlertQuery)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to check firing alerts")
	for _, series := range result.Data.Result {
		labels := helper.StripLabels(series.Metric, "alertname", "alertstate", "prometheus")
		violation := fmt.Sprintf("alert %s fired for %s seconds with labels: %s", series.Metric["alertname"], series.Value, helper.LabelsAsSelector(labels))
		if cause := allowedFiringAlerts.Matches(series); cause != nil {
			// TODO: this seems to never be firing? no search.ci results show allowed
			debug.Insert(fmt.Sprintf("%s result=allowed (%s)", violation, cause.Text))
			continue
		}
		if cause := firingAlertsWithBugs.Matches(series); cause != nil {
			knownViolations.Insert(fmt.Sprintf("%s result=allowed bug=%s", violation, cause.Text))
		} else {
			unexpectedViolations.Insert(fmt.Sprintf("%s result=failure", violation))
		}
	}

	// Invariant: There should be no pending alerts
	pendingAlertQuery := fmt.Sprintf(`
sort_desc(
  time() * ALERTS + 1
  -
  last_over_time((
    time() * ALERTS{alertname!~"Watchdog|AlertmanagerReceiversNotConfigured",alertstate="pending",severity!="info"}
    unless
    ALERTS offset 1s
  )[%[1]s:1s])
)
`, testDuration)
	result, err = helper.RunQuery(context.TODO(), prometheusClient, pendingAlertQuery)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to retrieve pending alerts")
	for _, series := range result.Data.Result {
		labels := helper.StripLabels(series.Metric, "alertname", "alertstate", "prometheus")
		violation := fmt.Sprintf("alert %s pending for %s seconds with labels: %s", series.Metric["alertname"], series.Value, helper.LabelsAsSelector(labels))
		if cause := allowedPendingAlerts.Matches(series); cause != nil {
			// TODO: this seems to never be firing? no search.ci results show allowed
			debug.Insert(fmt.Sprintf("%s result=allowed (%s)", violation, cause.Text))
			continue
		}
		if cause := pendingAlertsWithBugs.Matches(series); cause != nil {
			knownViolations.Insert(fmt.Sprintf("%s result=allowed bug=%s", violation, cause.Text))
		} else {
			// treat pending errors as a flake right now because we are still trying to determine the scope
			// TODO: move this to unexpectedViolations later
			unexpectedViolationsAsFlakes.Insert(fmt.Sprintf("%s result=allowed", violation))
		}
	}

	if len(debug) > 0 {
		framework.Logf("Alerts were detected which are allowed:\n\n%s", strings.Join(debug.List(), "\n"))
	}
	if flakes := sets.NewString().Union(knownViolations).Union(unexpectedViolations).Union(unexpectedViolationsAsFlakes); len(flakes) > 0 {
		// TODO: The two tests that had this duplicated code had slightly different ways of reporting flakes
		// that I do not fully understand the implications of. Fork the logic here.
		if f != nil {
			// when called from alert.go within an UpgradeTest with a framework available
			// f.TestSummaries is the part I'm unsure about here.
			disruption.FrameworkFlakef(f, "Unexpected alert behavior:\n\n%s", strings.Join(flakes.List(), "\n"))
		} else {
			// when called from prometheus.go with no framework available
			testresult.Flakef("Unexpected alert behavior:\n\n%s", strings.Join(flakes.List(), "\n"))
		}
	}
	framework.Logf("No alerts fired")

}
<commit_msg>More consistent alert result allow or reject<commit_after>package alerts

import (
	"context"
	"fmt"
	"strings"
	"time"

	o "github.com/onsi/gomega"
	configclient "github.com/openshift/client-go/config/clientset/versioned"
	"github.com/openshift/origin/pkg/synthetictests/allowedalerts"
	testresult "github.com/openshift/origin/pkg/test/ginkgo/result"
	"github.com/openshift/origin/test/extended/util/disruption"
	helper "github.com/openshift/origin/test/extended/util/prometheus"
	prometheusv1 "github.com/prometheus/client_golang/api/prometheus/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kubernetes/test/e2e/framework"
)

type allowedAlertsFunc func(configclient.Interface) (allowedFiringWithBugs, allowedFiring, allowedPendingWithBugs, allowedPending helper.MetricConditions)

// CheckAlerts will query prometheus and ensure no-unexpected alerts were pending or firing.
// Used both post-upgrade and post-conformance, with different allowances for each.
func CheckAlerts(allowancesFunc allowedAlertsFunc, prometheusClient prometheusv1.API, configClient configclient.Interface, testDuration time.Duration, f *framework.Framework) {
	firingAlertsWithBugs, allowedFiringAlerts, pendingAlertsWithBugs, allowedPendingAlerts :=
		allowancesFunc(configClient)

	// we exclude alerts that have their own separate tests.
	for _, alertTest := range allowedalerts.AllAlertTests(context.TODO(), nil, 0) {
		switch alertTest.AlertState() {
		case allowedalerts.AlertPending:
			// a pending test covers pending and everything above (firing)
			allowedPendingAlerts = append(allowedPendingAlerts,
				helper.MetricCondition{
					Selector: map[string]string{"alertname": alertTest.AlertName()},
					Text:     "has a separate e2e test",
				},
			)
			allowedFiringAlerts = append(allowedFiringAlerts,
				helper.MetricCondition{
					Selector: map[string]string{"alertname": alertTest.AlertName()},
					Text:     "has a separate e2e test",
				},
			)
		case allowedalerts.AlertInfo:
			// an info test covers all firing
			allowedFiringAlerts = append(allowedFiringAlerts,
				helper.MetricCondition{
					Selector: map[string]string{"alertname": alertTest.AlertName()},
					Text:     "has a separate e2e test",
				},
			)
		}
	}

	knownViolations := sets.NewString()
	unexpectedViolations := sets.NewString()
	unexpectedViolationsAsFlakes := sets.NewString()
	debug := sets.NewString()

	// Invariant: No non-info level alerts should have fired
	firingAlertQuery := fmt.Sprintf(`
sort_desc(
count_over_time(ALERTS{alertstate="firing",severity!="info",alertname!~"Watchdog|AlertmanagerReceiversNotConfigured"}[%[1]s:1s])
) > 0
`, testDuration)
	result, err := helper.RunQuery(context.TODO(), prometheusClient, firingAlertQuery)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to check firing alerts")
	for _, series := range result.Data.Result {
		labels := helper.StripLabels(series.Metric, "alertname", "alertstate", "prometheus")
		violation := fmt.Sprintf("alert %s fired for %s seconds with labels: %s", series.Metric["alertname"], series.Value, helper.LabelsAsSelector(labels))
		if cause := allowedFiringAlerts.Matches(series); cause != nil {
			// TODO: this seems to never be firing? no search.ci results show allowed
			debug.Insert(fmt.Sprintf("%s result=allow (%s)", violation, cause.Text))
			continue
		}
		if cause := firingAlertsWithBugs.Matches(series); cause != nil {
			knownViolations.Insert(fmt.Sprintf("%s result=allow bug=%s", violation, cause.Text))
		} else {
			unexpectedViolations.Insert(fmt.Sprintf("%s result=reject", violation))
		}
	}

	// Invariant: There should be no pending alerts
	pendingAlertQuery := fmt.Sprintf(`
sort_desc(
  time() * ALERTS + 1
  -
  last_over_time((
    time() * ALERTS{alertname!~"Watchdog|AlertmanagerReceiversNotConfigured",alertstate="pending",severity!="info"}
    unless
    ALERTS offset 1s
  )[%[1]s:1s])
)
`, testDuration)
	result, err = helper.RunQuery(context.TODO(), prometheusClient, pendingAlertQuery)
	o.Expect(err).NotTo(o.HaveOccurred(), "unable to retrieve pending alerts")
	for _, series := range result.Data.Result {
		labels := helper.StripLabels(series.Metric, "alertname", "alertstate", "prometheus")
		violation := fmt.Sprintf("alert %s pending for %s seconds with labels: %s", series.Metric["alertname"], series.Value, helper.LabelsAsSelector(labels))
		if cause := allowedPendingAlerts.Matches(series); cause != nil {
			// TODO: this seems to never be firing? no search.ci results show allowed
			debug.Insert(fmt.Sprintf("%s result=allow (%s)", violation, cause.Text))
			continue
		}
		if cause := pendingAlertsWithBugs.Matches(series); cause != nil {
			knownViolations.Insert(fmt.Sprintf("%s result=allow bug=%s", violation, cause.Text))
		} else {
			// treat pending errors as a flake right now because we are still trying to determine the scope
			// TODO: move this to unexpectedViolations later
			unexpectedViolationsAsFlakes.Insert(fmt.Sprintf("%s result=allow", violation))
		}
	}

	if len(debug) > 0 {
		framework.Logf("Alerts were detected which are allowed:\n\n%s", strings.Join(debug.List(), "\n"))
	}
	if flakes := sets.NewString().Union(knownViolations).Union(unexpectedViolations).Union(unexpectedViolationsAsFlakes); len(flakes) > 0 {
		// TODO: The two tests that had this duplicated code had slightly different ways of reporting flakes
		// that I do not fully understand the implications of. Fork the logic here.
		if f != nil {
			// when called from alert.go within an UpgradeTest with a framework available
			// f.TestSummaries is the part I'm unsure about here.
			disruption.FrameworkFlakef(f, "Unexpected alert behavior:\n\n%s", strings.Join(flakes.List(), "\n"))
		} else {
			// when called from prometheus.go with no framework available
			testresult.Flakef("Unexpected alert behavior:\n\n%s", strings.Join(flakes.List(), "\n"))
		}
	}
	framework.Logf("No alerts fired")

}
<|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 client

import (
	"fmt"

	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

// Retrieve a namespace pod constructed from the namespace limitations.
// Limitations cover pod resource limits and node selector if available
func RetrieveNamespacePod(client clientset.Interface, namespace string) (*v1.Pod, error) {
	ns, err := client.Core().Namespaces().Get(namespace, metav1.GetOptions{})
	if err != nil {
		return nil, fmt.Errorf("Namespace %v not found: %v", namespace, err)
	}

	namespacePod := v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "cluster-capacity-stub-container",
			Namespace: namespace,
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				v1.Container{
					Name:            "cluster-capacity-stub-container",
					Image:           "gcr.io/google_containers/pause:2.0",
					ImagePullPolicy: v1.PullAlways,
				},
			},
			RestartPolicy: v1.RestartPolicyOnFailure,
			DNSPolicy:     v1.DNSDefault,
		},
	}

	// Iterate through all limit ranges and pick the minimum of all related to pod constraints
	limits, err := client.Core().LimitRanges(namespace).List(metav1.ListOptions{})
	if err != nil {
		return nil, fmt.Errorf("Could not retrieve limit ranges for %v namespaces: %v", namespace, err)
	}

	resources := make(map[v1.ResourceName]*resource.Quantity)

	// TODO(jchaloup): extend the list of considered resources with other types
	resources[v1.ResourceMemory] = nil
	resources[v1.ResourceCPU] = nil
	resources[v1.ResourceNvidiaGPU] = nil

	for _, limit := range limits.Items {
		for _, item := range limit.Spec.Limits {
			if item.Type != v1.LimitTypePod {
				continue
			}

			for resourceType := range resources {
				amount, ok := item.Max[resourceType]
				if !ok {
					continue
				}
				if resources[resourceType] == nil || resources[resourceType].Cmp(amount) == 1 {
					resources[resourceType] = &amount
				}
			}
		}
	}

	nonzero := false
	for _, quantity := range resources {
		if quantity == nil {
			continue
		}

		if !quantity.IsZero() {
			nonzero = true
			break
		}
	}

	if nonzero {
		limitsResourceList := make(map[v1.ResourceName]resource.Quantity)
		requestsResourceList := make(map[v1.ResourceName]resource.Quantity)
		for key, val := range resources {
			if val == nil {
				continue
			}
			limitsResourceList[key] = *val
			requestsResourceList[key] = *val
		}

		namespacePod.Spec.Containers[0].Resources = v1.ResourceRequirements{
			Limits:   limitsResourceList,
			Requests: requestsResourceList,
		}

	}

	annotations := ns.GetAnnotations()
	if key, ok := annotations["openshift.io/node-selector"]; ok {
		nodeSelector, err := labels.ConvertSelectorToLabelsMap(key)
		if err != nil {
			return nil, fmt.Errorf("Unable to parse openshift.io/node-selector in %v namespace: %v", key, err)
		}
		namespacePod.Spec.NodeSelector = nodeSelector
	}

	return &namespacePod, nil
}
<commit_msg>Fix gofmt issue in pkg/client/nspod.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 client

import (
	"fmt"

	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

// Retrieve a namespace pod constructed from the namespace limitations.
// Limitations cover pod resource limits and node selector if available
func RetrieveNamespacePod(client clientset.Interface, namespace string) (*v1.Pod, error) {
	ns, err := client.Core().Namespaces().Get(namespace, metav1.GetOptions{})
	if err != nil {
		return nil, fmt.Errorf("Namespace %v not found: %v", namespace, err)
	}

	namespacePod := v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "cluster-capacity-stub-container",
			Namespace: namespace,
		},
		Spec: v1.PodSpec{
			Containers: []v1.Container{
				{
					Name:            "cluster-capacity-stub-container",
					Image:           "gcr.io/google_containers/pause:2.0",
					ImagePullPolicy: v1.PullAlways,
				},
			},
			RestartPolicy: v1.RestartPolicyOnFailure,
			DNSPolicy:     v1.DNSDefault,
		},
	}

	// Iterate through all limit ranges and pick the minimum of all related to pod constraints
	limits, err := client.Core().LimitRanges(namespace).List(metav1.ListOptions{})
	if err != nil {
		return nil, fmt.Errorf("Could not retrieve limit ranges for %v namespaces: %v", namespace, err)
	}

	resources := make(map[v1.ResourceName]*resource.Quantity)

	// TODO(jchaloup): extend the list of considered resources with other types
	resources[v1.ResourceMemory] = nil
	resources[v1.ResourceCPU] = nil
	resources[v1.ResourceNvidiaGPU] = nil

	for _, limit := range limits.Items {
		for _, item := range limit.Spec.Limits {
			if item.Type != v1.LimitTypePod {
				continue
			}

			for resourceType := range resources {
				amount, ok := item.Max[resourceType]
				if !ok {
					continue
				}
				if resources[resourceType] == nil || resources[resourceType].Cmp(amount) == 1 {
					resources[resourceType] = &amount
				}
			}
		}
	}

	nonzero := false
	for _, quantity := range resources {
		if quantity == nil {
			continue
		}

		if !quantity.IsZero() {
			nonzero = true
			break
		}
	}

	if nonzero {
		limitsResourceList := make(map[v1.ResourceName]resource.Quantity)
		requestsResourceList := make(map[v1.ResourceName]resource.Quantity)
		for key, val := range resources {
			if val == nil {
				continue
			}
			limitsResourceList[key] = *val
			requestsResourceList[key] = *val
		}

		namespacePod.Spec.Containers[0].Resources = v1.ResourceRequirements{
			Limits:   limitsResourceList,
			Requests: requestsResourceList,
		}

	}

	annotations := ns.GetAnnotations()
	if key, ok := annotations["openshift.io/node-selector"]; ok {
		nodeSelector, err := labels.ConvertSelectorToLabelsMap(key)
		if err != nil {
			return nil, fmt.Errorf("Unable to parse openshift.io/node-selector in %v namespace: %v", key, err)
		}
		namespacePod.Spec.NodeSelector = nodeSelector
	}

	return &namespacePod, 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 client

import (
	"fmt"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/resource"
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
	"k8s.io/kubernetes/pkg/labels"
)

// Retrieve a namespace pod constructed from the namespace limitations.
// Limitations cover pod resource limits and node selector if available
func RetrieveNamespacePod(client clientset.Interface, namespace string) (*api.Pod, error) {
	ns, err := client.Core().Namespaces().Get(namespace)
	if err != nil {
		return nil, fmt.Errorf("Namespace %v not found: %v", namespace, err)
	}

	// Iterate through all limit ranges and pick the minimum of all related to pod constraints
	limits, err := client.Core().LimitRanges(namespace).List(api.ListOptions{})
	if err != nil {
		return nil, fmt.Errorf("Could not retrieve limit ranges for %v namespaces: %v", namespace, err)
	}

	resources := make(map[api.ResourceName]*resource.Quantity)

	// TODO(jchaloup): extend the list of considered resources with other types
	resources[api.ResourceMemory] = nil
	resources[api.ResourceCPU] = nil
	resources[api.ResourceNvidiaGPU] = nil

	for _, limit := range limits.Items {
		for _, item := range limit.Spec.Limits {
			if item.Type != api.LimitTypePod {
				continue
			}

			for resourceType := range resources {
				amount, ok := item.Max[resourceType]
				if !ok {
					continue
				}
				if resources[resourceType] == nil || resources[resourceType].Cmp(amount) == 1 {
					resources[resourceType] = &amount
				}
			}
		}
	}

	nonzero := false
	for _, quantity := range resources {
		if quantity == nil {
			continue
		}

		if !quantity.IsZero() {
			nonzero = true
			break
		}
	}

	if !nonzero {
		return nil, fmt.Errorf("No resource limit set for pod in %v namespace", namespace)
	}

	limitsResourceList := make(map[api.ResourceName]resource.Quantity)
	requestsResourceList := make(map[api.ResourceName]resource.Quantity)
	for key, val := range resources {
		if val == nil {
			continue
		}
		limitsResourceList[key] = *val
		requestsResourceList[key] = *val
	}

	namespacePod := api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "cluster-capacity-stub-container",
			Namespace: namespace,
		},
		Spec: api.PodSpec{
			Containers: []api.Container{
				api.Container{
					Name:            "cluster-capacity-stub-container",
					Image:           "gcr.io/google_containers/pause:2.0",
					ImagePullPolicy: api.PullAlways,
					Resources: api.ResourceRequirements{
						Limits:   limitsResourceList,
						Requests: requestsResourceList,
					},
				},
			},
			RestartPolicy: api.RestartPolicyOnFailure,
			DNSPolicy:     api.DNSDefault,
		},
	}

	annotations := ns.GetAnnotations()
	if key, ok := annotations["openshift.io/node-selector"]; ok {
		nodeSelector, err := labels.ConvertSelectorToLabelsMap(key)
		if err != nil {
			return nil, fmt.Errorf("Unable to parse openshift.io/node-selector in %v namespace: %v", key, err)
		}
		namespacePod.Spec.NodeSelector = nodeSelector
	}

	return &namespacePod, nil
}
<commit_msg>Fix nspod.go for meta options.<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 client

import (
	"fmt"

	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/kubernetes/pkg/api"
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
)

// Retrieve a namespace pod constructed from the namespace limitations.
// Limitations cover pod resource limits and node selector if available
func RetrieveNamespacePod(client clientset.Interface, namespace string) (*api.Pod, error) {
	ns, err := client.Core().Namespaces().Get(namespace, metav1.GetOptions{})
	if err != nil {
		return nil, fmt.Errorf("Namespace %v not found: %v", namespace, err)
	}

	// Iterate through all limit ranges and pick the minimum of all related to pod constraints
	limits, err := client.Core().LimitRanges(namespace).List(metav1.ListOptions{})
	if err != nil {
		return nil, fmt.Errorf("Could not retrieve limit ranges for %v namespaces: %v", namespace, err)
	}

	resources := make(map[api.ResourceName]*resource.Quantity)

	// TODO(jchaloup): extend the list of considered resources with other types
	resources[api.ResourceMemory] = nil
	resources[api.ResourceCPU] = nil
	resources[api.ResourceNvidiaGPU] = nil

	for _, limit := range limits.Items {
		for _, item := range limit.Spec.Limits {
			if item.Type != api.LimitTypePod {
				continue
			}

			for resourceType := range resources {
				amount, ok := item.Max[resourceType]
				if !ok {
					continue
				}
				if resources[resourceType] == nil || resources[resourceType].Cmp(amount) == 1 {
					resources[resourceType] = &amount
				}
			}
		}
	}

	nonzero := false
	for _, quantity := range resources {
		if quantity == nil {
			continue
		}

		if !quantity.IsZero() {
			nonzero = true
			break
		}
	}

	if !nonzero {
		return nil, fmt.Errorf("No resource limit set for pod in %v namespace", namespace)
	}

	limitsResourceList := make(map[api.ResourceName]resource.Quantity)
	requestsResourceList := make(map[api.ResourceName]resource.Quantity)
	for key, val := range resources {
		if val == nil {
			continue
		}
		limitsResourceList[key] = *val
		requestsResourceList[key] = *val
	}

	namespacePod := api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "cluster-capacity-stub-container",
			Namespace: namespace,
		},
		Spec: api.PodSpec{
			Containers: []api.Container{
				api.Container{
					Name:            "cluster-capacity-stub-container",
					Image:           "gcr.io/google_containers/pause:2.0",
					ImagePullPolicy: api.PullAlways,
					Resources: api.ResourceRequirements{
						Limits:   limitsResourceList,
						Requests: requestsResourceList,
					},
				},
			},
			RestartPolicy: api.RestartPolicyOnFailure,
			DNSPolicy:     api.DNSDefault,
		},
	}

	annotations := ns.GetAnnotations()
	if key, ok := annotations["openshift.io/node-selector"]; ok {
		nodeSelector, err := labels.ConvertSelectorToLabelsMap(key)
		if err != nil {
			return nil, fmt.Errorf("Unable to parse openshift.io/node-selector in %v namespace: %v", key, err)
		}
		namespacePod.Spec.NodeSelector = nodeSelector
	}

	return &namespacePod, nil
}
<|endoftext|>


<commit_before>// Package mse (Message Stream Encryption) provides a transparent wrapper for bidirectional
// data streams (e.g. TCP transports) that prevents passive eavesdroping
// and thus protocol or content identification.
//
// It is also designed to provide limited protection against active MITM attacks
// and portscanning by requiring a weak shared secret to complete the handshake.
// You should note that the major design goal was payload and protocol obfuscation,
// not peer authentication and data integrity verification. Thus it does not offer
// protection against adversaries which already know the necessary data to establish
// connections (that is IP/Port/Shared Secret/Payload protocol).
//
// To minimize the load on systems that employ this protocol fast cryptographic
// methods have been chosen over maximum-security algorithms.
//
// See http://wiki.vuze.com/w/Message_Stream_Encryption for details.
package mse

import (
	"bufio"
	"bytes"
	crand "crypto/rand"
	"crypto/rc4"
	"crypto/sha1"
	"encoding/binary"
	"errors"
	"io"
	"io/ioutil"
	"math/rand"
)

// TODO seed rands

const (
	// p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563
	p            = 0xDEADBEEFDEADBEEF // TODO change this
	pSize        = 8                  // bytes TODO should be 96
	g            = 2
	sKey  uint64 = 1234 // TODO make it variable
)

var vc = make([]byte, 8)

type CryptoMethod uint32

// Crypto methods
const (
	PlainText CryptoMethod = 1 << iota
	RC4
)

const (
	part1_size           = 20 + 28
	part2_size           = 20
	handshake_size       = part1_size + part2_size
	enc_negotiation_size = 8 + 4 + 2
	enc_pad_size         = 512
	enc_pad_read_size    = 96 + enc_pad_size + 20
	buffer_size          = enc_pad_read_size + 20 + enc_negotiation_size + enc_pad_size + 2 + handshake_size + 5
)

type Stream struct {
	rw      io.ReadWriter
	x       uint64 // private key // TODO must be 160 bits
	y       uint64 // public key
	yRemote uint64
	cipher  *rc4.Cipher
}

func NewStream(rw io.ReadWriter) *Stream {
	s := Stream{
		rw: rw,
		x:  uint64(rand.Int63()),
	}
	s.y = (g ^ s.x) % p
	return &s
}

func (s *Stream) HandshakeOutgoing(cryptoProvide CryptoMethod) (selected CryptoMethod, err error) {
	writeBuf := bufio.NewWriter(s.rw)

	// Step 1 | A->B: Diffie Hellman Ya, PadA
	err = binary.Write(writeBuf, binary.BigEndian, &s.y)
	if err != nil {
		return
	}
	padA, err := pad()
	if err != nil {
		return
	}
	_, err = writeBuf.Write(padA)
	if err != nil {
		return
	}
	err = writeBuf.Flush()
	if err != nil {
		return
	}

	// Step 2 | B->A: Diffie Hellman Yb, PadB
	readBuf := make([]byte, pSize+512)
	_, err = io.ReadAtLeast(s.rw, readBuf, pSize)
	if err != nil {
		return
	}
	err = binary.Read(bytes.NewReader(readBuf), binary.BigEndian, &s.yRemote)
	if err != nil {
		return
	}
	S := (s.yRemote ^ s.x) % p
	s.cipher, err = rc4.NewCipher(rc4Key("keyA", S, sKey))
	if err != nil {
		return
	}

	// Step 3 | A->B: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA)
	_, err = writeBuf.Write(hash("req1", S))
	if err != nil {
		return
	}
	req2 := hash("req2", sKey)
	req3 := hash("req3", S)
	for i := 0; i < sha1.Size; i++ {
		req2[i] ^= req3[i]
	}
	_, err = writeBuf.Write(req2)
	if err != nil {
		return
	}
	discard := make([]byte, 1024)
	s.cipher.XORKeyStream(discard, discard)
	encBuf := bytes.NewBuffer(make([]byte, 0, 8+4+2+0+2))
	_, err = encBuf.Write(vc)
	if err != nil {
		return
	}
	err = binary.Write(encBuf, binary.BigEndian, cryptoProvide)
	if err != nil {
		return
	}
	err = binary.Write(encBuf, binary.BigEndian, uint16(0)) // len(PadC)
	if err != nil {
		return
	}
	err = binary.Write(encBuf, binary.BigEndian, uint16(0)) // len(IA)
	if err != nil {
		return
	}
	encBytes := encBuf.Bytes()
	s.cipher.XORKeyStream(encBytes, encBytes)
	writeBuf.Write(encBytes)
	if err != nil {
		return
	}
	err = writeBuf.Flush()
	if err != nil {
		return
	}

	// Step 4 | B->A: ENCRYPT(VC, crypto_select, len(padD), padD), ENCRYPT2(Payload Stream)
	vcRead, err := s.decrypt(8)
	if err != nil {
		return
	}
	if bytes.Compare(vcRead, vc) != 0 {
		err = errors.New("invalid VC")
		return
	}
	cryptoSelect, err := s.decrypt(4)
	if err != nil {
		return
	}
	err = binary.Read(bytes.NewReader(cryptoSelect), binary.BigEndian, &selected)
	if err != nil {
		return
	}
	// TODO check selected crypto is provided
	lenPadDBytes, err := s.decrypt(2)
	if err != nil {
		return
	}
	var lenPadD uint16
	err = binary.Read(bytes.NewReader(lenPadDBytes), binary.BigEndian, &lenPadD)
	if err != nil {
		return
	}
	_, err = io.CopyN(ioutil.Discard, s.rw, int64(lenPadD))
	if err != nil {
		return
	}

	return selected, nil

	// Step 5 | A->B: ENCRYPT2(Payload Stream)
}

func (s *Stream) decrypt(n int) ([]byte, error) {
	buf := make([]byte, n)
	_, err := io.ReadFull(s.rw, buf)
	if err != nil {
		return nil, err
	}
	s.cipher.XORKeyStream(buf, buf)
	return buf, nil
}

func hash(s string, key uint64) []byte {
	h := sha1.New()
	h.Write([]byte(s))
	binary.Write(h, binary.BigEndian, &key)
	return h.Sum(nil)
}

func rc4Key(prefix string, s uint64, sKey uint64) []byte {
	h := sha1.New()
	h.Write([]byte(prefix))
	binary.Write(h, binary.BigEndian, &s)
	binary.Write(h, binary.BigEndian, &sKey)
	return h.Sum(nil)
}

func pad() ([]byte, error) {
	b := make([]byte, rand.Intn(512))
	_, err := crand.Read(b)
	return b, err
}

func (s *Stream) HandshakeIncoming(cryptoSelect func(cryptoProvide CryptoMethod) (CryptoMethod, error)) error {
	// Step 1 | A->B: Diffie Hellman Ya, PadA
	readBuf := make([]byte, pSize+512)
	_, err := io.ReadAtLeast(s.rw, readBuf, pSize)
	if err != nil {
		return err
	}
	err = binary.Read(bytes.NewReader(readBuf), binary.BigEndian, &s.yRemote)
	if err != nil {
		return err
	}
	S := (s.yRemote ^ s.x) % p
	s.cipher, err = rc4.NewCipher(rc4Key("keyB", S, sKey))
	if err != nil {
		return err
	}

	// Step 2 | B->A: Diffie Hellman Yb, PadB
	writeBuf := bufio.NewWriter(s.rw)
	err = binary.Write(writeBuf, binary.BigEndian, &s.y)
	if err != nil {
		return err
	}
	padB, err := pad()
	_, err = writeBuf.Write(padB)
	if err != nil {
		return err
	}
	err = writeBuf.Flush()
	if err != nil {
		return err
	}

	// Step 3 | A->B: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA)
	_, err = io.CopyN(ioutil.Discard, s.rw, 20) // TODO check S hash
	if err != nil {
		return err
	}
	_, err = io.CopyN(ioutil.Discard, s.rw, 20) // TODO check SKEY hash
	if err != nil {
		return err
	}
	_, err = s.decrypt(8) // TODO vc read
	if err != nil {
		return err
	}
	// TODO check vc is correct
	cryptoProvideBytes, err := s.decrypt(4)
	if err != nil {
		return err
	}
	var cryptoProvide CryptoMethod
	err = binary.Read(bytes.NewReader(cryptoProvideBytes), binary.BigEndian, &cryptoProvide)
	if err != nil {
		return err
	}
	selected, err := cryptoSelect(cryptoProvide)
	if err != nil {
		return err
	}
	_, err = io.CopyN(ioutil.Discard, s.rw, 4) // TODO padC and IA
	if err != nil {
		return err
	}

	// Step 4 | B->A: ENCRYPT(VC, crypto_select, len(padD), padD), ENCRYPT2(Payload Stream)
	encBuf := bytes.NewBuffer(make([]byte, 0, 8+4+2))
	_, err = encBuf.Write(vc)
	if err != nil {
		return err
	}
	err = binary.Write(encBuf, binary.BigEndian, selected)
	if err != nil {
		return err
	}
	err = binary.Write(encBuf, binary.BigEndian, uint16(0)) // len(PadC)
	if err != nil {
		return err
	}
	encBytes := encBuf.Bytes()
	s.cipher.XORKeyStream(encBytes, encBytes)
	writeBuf.Write(encBytes)
	if err != nil {
		return err
	}
	err = writeBuf.Flush()
	if err != nil {
		return err
	}

	// Step 5 | A->B: ENCRYPT2(Payload Stream)
	return nil
}

func (s *Stream) Read(p []byte) (n int, err error) {
	n, err = s.Read(p)
	s.cipher.XORKeyStream(p, p)
	return
}

func (s *Stream) Write(p []byte) (n int, err error) {
	n, err = s.Write(p)
	s.cipher.XORKeyStream(p, p)
	return
}
<commit_msg>check hashes<commit_after>// Package mse (Message Stream Encryption) provides a transparent wrapper for bidirectional
// data streams (e.g. TCP transports) that prevents passive eavesdroping
// and thus protocol or content identification.
//
// It is also designed to provide limited protection against active MITM attacks
// and portscanning by requiring a weak shared secret to complete the handshake.
// You should note that the major design goal was payload and protocol obfuscation,
// not peer authentication and data integrity verification. Thus it does not offer
// protection against adversaries which already know the necessary data to establish
// connections (that is IP/Port/Shared Secret/Payload protocol).
//
// To minimize the load on systems that employ this protocol fast cryptographic
// methods have been chosen over maximum-security algorithms.
//
// See http://wiki.vuze.com/w/Message_Stream_Encryption for details.
package mse

import (
	"bufio"
	"bytes"
	crand "crypto/rand"
	"crypto/rc4"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
)

// TODO seed rands

const (
	// p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563
	p            = 0xDEADBEEFDEADBEEF // TODO change this
	pSize        = 8                  // bytes TODO should be 96
	g            = 2
	sKey  uint64 = 1234 // TODO make it variable
)

var vc = make([]byte, 8)

type CryptoMethod uint32

// Crypto methods
const (
	PlainText CryptoMethod = 1 << iota
	RC4
)

const (
	part1_size           = 20 + 28
	part2_size           = 20
	handshake_size       = part1_size + part2_size
	enc_negotiation_size = 8 + 4 + 2
	enc_pad_size         = 512
	enc_pad_read_size    = 96 + enc_pad_size + 20
	buffer_size          = enc_pad_read_size + 20 + enc_negotiation_size + enc_pad_size + 2 + handshake_size + 5
)

type Stream struct {
	rw      io.ReadWriter
	x       uint64 // private key // TODO must be 160 bits
	y       uint64 // public key
	yRemote uint64
	cipher  *rc4.Cipher
}

func NewStream(rw io.ReadWriter) *Stream {
	s := Stream{
		rw: rw,
		x:  uint64(rand.Int63()),
	}
	s.y = (g ^ s.x) % p
	return &s
}

func (s *Stream) HandshakeOutgoing(cryptoProvide CryptoMethod) (selected CryptoMethod, err error) {
	writeBuf := bufio.NewWriter(s.rw)

	// Step 1 | A->B: Diffie Hellman Ya, PadA
	err = binary.Write(writeBuf, binary.BigEndian, &s.y)
	if err != nil {
		return
	}
	padA, err := pad()
	if err != nil {
		return
	}
	_, err = writeBuf.Write(padA)
	if err != nil {
		return
	}
	err = writeBuf.Flush()
	if err != nil {
		return
	}

	// Step 2 | B->A: Diffie Hellman Yb, PadB
	readBuf := make([]byte, pSize+512)
	_, err = io.ReadAtLeast(s.rw, readBuf, pSize)
	if err != nil {
		return
	}
	err = binary.Read(bytes.NewReader(readBuf), binary.BigEndian, &s.yRemote)
	if err != nil {
		return
	}
	S := (s.yRemote ^ s.x) % p
	s.cipher, err = rc4.NewCipher(rc4Key("keyA", S, sKey))
	if err != nil {
		return
	}

	// Step 3 | A->B: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA)
	_, err = writeBuf.Write(hash("req1", S))
	if err != nil {
		return
	}
	req2 := hash("req2", sKey)
	req3 := hash("req3", S)
	for i := 0; i < sha1.Size; i++ {
		req2[i] ^= req3[i]
	}
	_, err = writeBuf.Write(req2)
	if err != nil {
		return
	}
	discard := make([]byte, 1024)
	s.cipher.XORKeyStream(discard, discard)
	encBuf := bytes.NewBuffer(make([]byte, 0, 8+4+2+0+2))
	_, err = encBuf.Write(vc)
	if err != nil {
		return
	}
	err = binary.Write(encBuf, binary.BigEndian, cryptoProvide)
	if err != nil {
		return
	}
	err = binary.Write(encBuf, binary.BigEndian, uint16(0)) // len(PadC)
	if err != nil {
		return
	}
	err = binary.Write(encBuf, binary.BigEndian, uint16(0)) // len(IA)
	if err != nil {
		return
	}
	encBytes := encBuf.Bytes()
	s.cipher.XORKeyStream(encBytes, encBytes)
	writeBuf.Write(encBytes)
	if err != nil {
		return
	}
	err = writeBuf.Flush()
	if err != nil {
		return
	}

	// Step 4 | B->A: ENCRYPT(VC, crypto_select, len(padD), padD), ENCRYPT2(Payload Stream)
	vcRead, err := s.decrypt(8)
	if err != nil {
		return
	}
	if bytes.Compare(vcRead, vc) != 0 {
		err = errors.New("invalid VC")
		return
	}
	cryptoSelect, err := s.decrypt(4)
	if err != nil {
		return
	}
	err = binary.Read(bytes.NewReader(cryptoSelect), binary.BigEndian, &selected)
	if err != nil {
		return
	}
	// TODO check selected crypto is provided
	lenPadDBytes, err := s.decrypt(2)
	if err != nil {
		return
	}
	var lenPadD uint16
	err = binary.Read(bytes.NewReader(lenPadDBytes), binary.BigEndian, &lenPadD)
	if err != nil {
		return
	}
	_, err = io.CopyN(ioutil.Discard, s.rw, int64(lenPadD))
	if err != nil {
		return
	}

	return selected, nil

	// Step 5 | A->B: ENCRYPT2(Payload Stream)
}

func (s *Stream) decrypt(n int) ([]byte, error) {
	buf := make([]byte, n)
	_, err := io.ReadFull(s.rw, buf)
	if err != nil {
		return nil, err
	}
	s.cipher.XORKeyStream(buf, buf)
	return buf, nil
}

func hash(prefix string, key uint64) []byte {
	h := sha1.New()
	h.Write([]byte(prefix))
	binary.Write(h, binary.BigEndian, &key)
	return h.Sum(nil)
}

func rc4Key(prefix string, s uint64, sKey uint64) []byte {
	h := sha1.New()
	h.Write([]byte(prefix))
	binary.Write(h, binary.BigEndian, &s)
	binary.Write(h, binary.BigEndian, &sKey)
	return h.Sum(nil)
}

func pad() ([]byte, error) {
	b := make([]byte, rand.Intn(512))
	_, err := crand.Read(b)
	return b, err
}

func (s *Stream) HandshakeIncoming(cryptoSelect func(cryptoProvide CryptoMethod) (CryptoMethod, error)) error {
	// Step 1 | A->B: Diffie Hellman Ya, PadA
	readBuf := make([]byte, pSize+512)
	_, err := io.ReadAtLeast(s.rw, readBuf, pSize)
	if err != nil {
		return err
	}
	err = binary.Read(bytes.NewReader(readBuf), binary.BigEndian, &s.yRemote)
	if err != nil {
		return err
	}
	S := (s.yRemote ^ s.x) % p
	s.cipher, err = rc4.NewCipher(rc4Key("keyB", S, sKey))
	if err != nil {
		return err
	}

	// Step 2 | B->A: Diffie Hellman Yb, PadB
	writeBuf := bufio.NewWriter(s.rw)
	err = binary.Write(writeBuf, binary.BigEndian, &s.y)
	if err != nil {
		return err
	}
	padB, err := pad()
	_, err = writeBuf.Write(padB)
	if err != nil {
		return err
	}
	err = writeBuf.Flush()
	if err != nil {
		return err
	}

	// Step 3 | A->B: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA)
	hashRead := make([]byte, 20)
	_, err = io.ReadFull(s.rw, hashRead)
	if err != nil {
		return err
	}
	hash1Calc := hash("req1", S)
	if !bytes.Equal(hashRead, hash1Calc) {
		err = errors.New("invalid S hash")
	}
	_, err = io.ReadFull(s.rw, hashRead)
	if err != nil {
		return err
	}
	hash2Calc := hash("req2", sKey)
	hash3Calc := hash("req3", S)
	for i := 0; i < sha1.Size; i++ {
		hash3Calc[i] ^= hash2Calc[i]
	}
	if !bytes.Equal(hashRead, hash3Calc) {
		err = errors.New("invalid SKEY hash")
	}
	discard := make([]byte, 1024)
	s.cipher.XORKeyStream(discard, discard)
	vcRead, err := s.decrypt(8)
	if err != nil {
		return err
	}
	if !bytes.Equal(vcRead, vc) {
		return fmt.Errorf("invalid VC: %s", hex.EncodeToString(vcRead))
	}
	cryptoProvideBytes, err := s.decrypt(4)
	if err != nil {
		return err
	}
	var cryptoProvide CryptoMethod
	err = binary.Read(bytes.NewReader(cryptoProvideBytes), binary.BigEndian, &cryptoProvide)
	if err != nil {
		return err
	}
	selected, err := cryptoSelect(cryptoProvide)
	if err != nil {
		return err
	}
	_, err = io.CopyN(ioutil.Discard, s.rw, 4) // TODO padC and IA
	if err != nil {
		return err
	}

	// Step 4 | B->A: ENCRYPT(VC, crypto_select, len(padD), padD), ENCRYPT2(Payload Stream)
	encBuf := bytes.NewBuffer(make([]byte, 0, 8+4+2))
	_, err = encBuf.Write(vc)
	if err != nil {
		return err
	}
	err = binary.Write(encBuf, binary.BigEndian, selected)
	if err != nil {
		return err
	}
	err = binary.Write(encBuf, binary.BigEndian, uint16(0)) // len(PadC)
	if err != nil {
		return err
	}
	encBytes := encBuf.Bytes()
	s.cipher.XORKeyStream(encBytes, encBytes)
	writeBuf.Write(encBytes)
	if err != nil {
		return err
	}
	err = writeBuf.Flush()
	if err != nil {
		return err
	}

	// Step 5 | A->B: ENCRYPT2(Payload Stream)
	return nil
}

func (s *Stream) Read(p []byte) (n int, err error) {
	n, err = s.Read(p)
	s.cipher.XORKeyStream(p, p)
	return
}

func (s *Stream) Write(p []byte) (n int, err error) {
	n, err = s.Write(p)
	s.cipher.XORKeyStream(p, p)
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2020 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 kepctl

import (
	"fmt"
	"regexp"

	"github.com/pkg/errors"

	"k8s.io/enhancements/pkg/kepval/keps"
	"k8s.io/enhancements/pkg/kepval/keps/validations"
)

var (
	// SupportedOutputOpts stores all allowed query output formats
	SupportedOutputOpts = []string{
		"table",
		"json",
		"yaml",
	}

	// DefaultOutputOpt is the default output format for kepctl query
	DefaultOutputOpt = "table"
)

type QueryOpts struct {
	CommonArgs
	SIG         []string
	Status      []string
	Stage       []string
	PRRApprover []string
	IncludePRs  bool
	Output      string
}

// Validate checks the args and cleans them up if needed
func (c *QueryOpts) Validate(args []string) error {
	if len(c.SIG) > 0 {
		sigs, err := selectByRegexp(validations.Sigs(), c.SIG)
		if err != nil {
			return err
		}
		if len(sigs) == 0 {
			return fmt.Errorf("No SIG matches any of the passed regular expressions")
		}
		c.SIG = sigs
	}

	// check if the Output specified is one of "", "json" or "yaml"
	if !sliceContains(SupportedOutputOpts, c.Output) {
		return fmt.Errorf("unsupported output format: %s. Valid values: %v", c.Output, SupportedOutputOpts)
	}

	//TODO: check the valid values of stage, status, etc.
	return nil
}

// Query searches the local repo and possibly GitHub for KEPs
// that match the search criteria.
func (c *Client) Query(opts QueryOpts) error {
	fmt.Fprintf(c.Out, "Searching for KEPs...\n")
	repoPath, err := c.findEnhancementsRepo(opts.CommonArgs)
	if err != nil {
		return errors.Wrap(err, "unable to search KEPs")
	}

	c.SetGitHubToken(opts.CommonArgs)

	var allKEPs []*keps.Proposal
	// load the KEPs for each listed SIG
	for _, sig := range opts.SIG {
		// KEPs in the local filesystem
		allKEPs = append(allKEPs, c.loadLocalKEPs(repoPath, sig)...)

		// Open PRs; existing KEPs with open PRs will be shown twice
		if opts.IncludePRs {
			prKeps, err := c.loadKEPPullRequests(sig)
			if err != nil {
				fmt.Fprintf(c.Err, "error searching for KEP PRs from %s: %s\n", sig, err)
			}
			if prKeps != nil {
				allKEPs = append(allKEPs, prKeps...)
			}
		}
	}

	// filter the KEPs by criteria
	allowedStatus := sliceToMap(opts.Status)
	allowedStage := sliceToMap(opts.Stage)
	allowedPRR := sliceToMap(opts.PRRApprover)

	var keep []*keps.Proposal
	for _, k := range allKEPs {
		if len(opts.Status) > 0 && !allowedStatus[k.Status] {
			continue
		}
		if len(opts.Stage) > 0 && !allowedStage[k.Stage] {
			continue
		}
		if len(opts.PRRApprover) > 0 && !atLeastOne(k.PRRApprovers, allowedPRR) {
			continue
		}
		keep = append(keep, k)
	}

	c.PrintTable(DefaultPrintConfigs("LastUpdated", "Stage", "Status", "SIG", "Authors", "Title", "Link"), keep)
	return nil
}

func sliceToMap(s []string) map[string]bool {
	m := make(map[string]bool, len(s))
	for _, v := range s {
		m[v] = true
	}
	return m
}

func sliceContains(s []string, e string) bool {
	for _, k := range s {
		if k == e {
			return true
		}
	}

	return false
}

// returns all strings in vals that match at least one
// regexp in regexps
func selectByRegexp(vals []string, regexps []string) ([]string, error) {
	var matches []string
	for _, s := range vals {
		for _, r := range regexps {
			found, err := regexp.MatchString(r, s)
			if err != nil {
				return matches, err
			}
			if found {
				matches = append(matches, s)
				break
			}
		}
	}
	return matches, nil
}

// returns true if at least one of vals is in the allowed map
func atLeastOne(vals []string, allowed map[string]bool) bool {
	for _, v := range vals {
		if allowed[v] {
			return true
		}
	}

	return false
}
<commit_msg>Add switching logic for printers in different formats<commit_after>/*
Copyright 2020 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 kepctl

import (
	"fmt"
	"regexp"

	"github.com/pkg/errors"

	"k8s.io/enhancements/pkg/kepval/keps"
	"k8s.io/enhancements/pkg/kepval/keps/validations"
)

var (
	// SupportedOutputOpts stores all allowed query output formats
	SupportedOutputOpts = []string{
		"table",
		"json",
		"yaml",
	}

	// DefaultOutputOpt is the default output format for kepctl query
	DefaultOutputOpt = "table"
)

type QueryOpts struct {
	CommonArgs
	SIG         []string
	Status      []string
	Stage       []string
	PRRApprover []string
	IncludePRs  bool
	Output      string
}

// Validate checks the args and cleans them up if needed
func (c *QueryOpts) Validate(args []string) error {
	if len(c.SIG) > 0 {
		sigs, err := selectByRegexp(validations.Sigs(), c.SIG)
		if err != nil {
			return err
		}
		if len(sigs) == 0 {
			return fmt.Errorf("No SIG matches any of the passed regular expressions")
		}
		c.SIG = sigs
	}

	// check if the Output specified is one of "", "json" or "yaml"
	if !sliceContains(SupportedOutputOpts, c.Output) {
		return fmt.Errorf("unsupported output format: %s. Valid values: %v", c.Output, SupportedOutputOpts)
	}

	//TODO: check the valid values of stage, status, etc.
	return nil
}

// Query searches the local repo and possibly GitHub for KEPs
// that match the search criteria.
func (c *Client) Query(opts QueryOpts) error {
	fmt.Fprintf(c.Out, "Searching for KEPs...\n")
	repoPath, err := c.findEnhancementsRepo(opts.CommonArgs)
	if err != nil {
		return errors.Wrap(err, "unable to search KEPs")
	}

	c.SetGitHubToken(opts.CommonArgs)

	var allKEPs []*keps.Proposal
	// load the KEPs for each listed SIG
	for _, sig := range opts.SIG {
		// KEPs in the local filesystem
		allKEPs = append(allKEPs, c.loadLocalKEPs(repoPath, sig)...)

		// Open PRs; existing KEPs with open PRs will be shown twice
		if opts.IncludePRs {
			prKeps, err := c.loadKEPPullRequests(sig)
			if err != nil {
				fmt.Fprintf(c.Err, "error searching for KEP PRs from %s: %s\n", sig, err)
			}
			if prKeps != nil {
				allKEPs = append(allKEPs, prKeps...)
			}
		}
	}

	// filter the KEPs by criteria
	allowedStatus := sliceToMap(opts.Status)
	allowedStage := sliceToMap(opts.Stage)
	allowedPRR := sliceToMap(opts.PRRApprover)

	var keep []*keps.Proposal
	for _, k := range allKEPs {
		if len(opts.Status) > 0 && !allowedStatus[k.Status] {
			continue
		}
		if len(opts.Stage) > 0 && !allowedStage[k.Stage] {
			continue
		}
		if len(opts.PRRApprover) > 0 && !atLeastOne(k.PRRApprovers, allowedPRR) {
			continue
		}
		keep = append(keep, k)
	}

	switch opts.Output {
	case "table":
		c.PrintTable(DefaultPrintConfigs("LastUpdated", "Stage", "Status", "SIG", "Authors", "Title", "Link"), keep)
	case "yaml":
		c.PrintYAML(keep)
	case "json":
		c.PrintJSON(keep)
	default:
		// this check happens as a validation step in cobra as well
		// added it for additional verbosity
		return fmt.Errorf("unsupported output format: %s. Valid values: %s", opts.Output, SupportedOutputOpts)
	}
	return nil
}

func sliceToMap(s []string) map[string]bool {
	m := make(map[string]bool, len(s))
	for _, v := range s {
		m[v] = true
	}
	return m
}

func sliceContains(s []string, e string) bool {
	for _, k := range s {
		if k == e {
			return true
		}
	}

	return false
}

// returns all strings in vals that match at least one
// regexp in regexps
func selectByRegexp(vals []string, regexps []string) ([]string, error) {
	var matches []string
	for _, s := range vals {
		for _, r := range regexps {
			found, err := regexp.MatchString(r, s)
			if err != nil {
				return matches, err
			}
			if found {
				matches = append(matches, s)
				break
			}
		}
	}
	return matches, nil
}

// returns true if at least one of vals is in the allowed map
func atLeastOne(vals []string, allowed map[string]bool) bool {
	for _, v := range vals {
		if allowed[v] {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>package logproto

import (
	// trick dep into including this, needed by the generated code.
	_ "github.com/cortexproject/cortex/pkg/chunk/storage"
	_ "github.com/gogo/protobuf/types"
)
<commit_msg>Removing this file used to trick dep into importing packages, the second import already exists in the logproto.pb.go file and the first import is already imported other places in our code. This should fix the anyone using the logproto.pb.go file from registering a bunch of cortex metrics.<commit_after><|endoftext|>


<commit_before>package moq

// moqImports are the imports all moq files get.
var moqImports = []string{}

// moqTemplate is the template for mocked code.
var moqTemplate = `// Code generated by moq; DO NOT EDIT.
// github.com/matryer/moq

package {{.PackageName}}

import (
{{- range .Imports }}
	"{{.}}"
{{- end }}
)

{{ range $i, $obj := .Objects -}}
var (
{{- range .Methods }}
	lock{{$obj.InterfaceName}}Mock{{.Name}}	sync.RWMutex
{{- end }}
)

// {{.InterfaceName}}Mock is a mock implementation of {{.InterfaceName}}.
//
//     func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) {
//
//         // make and configure a mocked {{.InterfaceName}}
//         mocked{{.InterfaceName}} := &{{.InterfaceName}}Mock{ {{ range .Methods }}
//             {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} {
// 	               panic("TODO: mock out the {{.Name}} method")
//             },{{- end }}
//         }
//
//         // TODO: use mocked{{.InterfaceName}} in code that requires {{.InterfaceName}}
//         //       and then make assertions.
//
//     }
type {{.InterfaceName}}Mock struct {
{{- range .Methods }}
	// {{.Name}}Func mocks the {{.Name}} method.
	{{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}}
{{ end }}
	// calls tracks calls to the methods.
	calls struct {
{{- range .Methods }}
		// {{ .Name }} holds details about calls to the {{.Name}} method.
		{{ .Name }} []struct {
			{{- range .Params }}
			// {{ .Name | Exported }} is the {{ .Name }} argument value.
			{{ .Name | Exported }} {{ .Type }}
			{{- end }}
		}
{{- end }}
	}
}
{{ range .Methods }}
// {{.Name}} calls {{.Name}}Func.
func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} {
	if mock.{{.Name}}Func == nil {
		panic("{{$obj.InterfaceName}}Mock.{{.Name}}Func: method is nil but {{$obj.InterfaceName}}.{{.Name}} was just called")
	}
	callInfo := struct {
		{{- range .Params }}
		{{ .Name | Exported }} {{ .Type }}
		{{- end }}
	}{
		{{- range .Params }}
		{{ .Name | Exported }}: {{ .Name }},
		{{- end }}
	}
	lock{{$obj.InterfaceName}}Mock{{.Name}}.Lock()
	mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo)
	lock{{$obj.InterfaceName}}Mock{{.Name}}.Unlock()
{{- if .ReturnArglist }}
	return mock.{{.Name}}Func({{.ArgCallList}})
{{- else }}
	mock.{{.Name}}Func({{.ArgCallList}})
{{- end }}
}

// {{.Name}}Calls gets all the calls that were made to {{.Name}}.
// Check the length with:
//     len(mocked{{$obj.InterfaceName}}.{{.Name}}Calls())
func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}Calls() []struct {
		{{- range .Params }}
		{{ .Name | Exported }} {{ .Type }}
		{{- end }}
	} {
	var calls []struct {
		{{- range .Params }}
		{{ .Name | Exported }} {{ .Type }}
		{{- end }}
	}
	lock{{$obj.InterfaceName}}Mock{{.Name}}.RLock()
	calls = mock.calls.{{.Name}}
	lock{{$obj.InterfaceName}}Mock{{.Name}}.RUnlock()
	return calls
}
{{ end -}}
{{ end -}}`
<commit_msg>Remove TODO comments from template.go<commit_after>package moq

// moqImports are the imports all moq files get.
var moqImports = []string{}

// moqTemplate is the template for mocked code.
var moqTemplate = `// Code generated by moq; DO NOT EDIT.
// github.com/matryer/moq

package {{.PackageName}}

import (
{{- range .Imports }}
	"{{.}}"
{{- end }}
)

{{ range $i, $obj := .Objects -}}
var (
{{- range .Methods }}
	lock{{$obj.InterfaceName}}Mock{{.Name}}	sync.RWMutex
{{- end }}
)

// {{.InterfaceName}}Mock is a mock implementation of {{.InterfaceName}}.
//
//     func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) {
//
//         // make and configure a mocked {{.InterfaceName}}
//         mocked{{.InterfaceName}} := &{{.InterfaceName}}Mock{ {{ range .Methods }}
//             {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} {
// 	               panic("mock out the {{.Name}} method")
//             },{{- end }}
//         }
//
//         // use mocked{{.InterfaceName}} in code that requires {{.InterfaceName}}
//         // and then make assertions.
//
//     }
type {{.InterfaceName}}Mock struct {
{{- range .Methods }}
	// {{.Name}}Func mocks the {{.Name}} method.
	{{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}}
{{ end }}
	// calls tracks calls to the methods.
	calls struct {
{{- range .Methods }}
		// {{ .Name }} holds details about calls to the {{.Name}} method.
		{{ .Name }} []struct {
			{{- range .Params }}
			// {{ .Name | Exported }} is the {{ .Name }} argument value.
			{{ .Name | Exported }} {{ .Type }}
			{{- end }}
		}
{{- end }}
	}
}
{{ range .Methods }}
// {{.Name}} calls {{.Name}}Func.
func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} {
	if mock.{{.Name}}Func == nil {
		panic("{{$obj.InterfaceName}}Mock.{{.Name}}Func: method is nil but {{$obj.InterfaceName}}.{{.Name}} was just called")
	}
	callInfo := struct {
		{{- range .Params }}
		{{ .Name | Exported }} {{ .Type }}
		{{- end }}
	}{
		{{- range .Params }}
		{{ .Name | Exported }}: {{ .Name }},
		{{- end }}
	}
	lock{{$obj.InterfaceName}}Mock{{.Name}}.Lock()
	mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo)
	lock{{$obj.InterfaceName}}Mock{{.Name}}.Unlock()
{{- if .ReturnArglist }}
	return mock.{{.Name}}Func({{.ArgCallList}})
{{- else }}
	mock.{{.Name}}Func({{.ArgCallList}})
{{- end }}
}

// {{.Name}}Calls gets all the calls that were made to {{.Name}}.
// Check the length with:
//     len(mocked{{$obj.InterfaceName}}.{{.Name}}Calls())
func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}Calls() []struct {
		{{- range .Params }}
		{{ .Name | Exported }} {{ .Type }}
		{{- end }}
	} {
	var calls []struct {
		{{- range .Params }}
		{{ .Name | Exported }} {{ .Type }}
		{{- end }}
	}
	lock{{$obj.InterfaceName}}Mock{{.Name}}.RLock()
	calls = mock.calls.{{.Name}}
	lock{{$obj.InterfaceName}}Mock{{.Name}}.RUnlock()
	return calls
}
{{ end -}}
{{ end -}}`
<|endoftext|>


<commit_before>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package present

import (
	"fmt"
	"html/template"
	"log"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"unicode"
)

// Is the playground available?
var PlayEnabled = false

// TOOD(adg): replace the PlayEnabled flag with something less spaghetti-like.
// Instead this will probably be determined by a template execution Context
// value that contains various global metadata required when rendering
// templates.

func init() {
	Register("code", parseCode)
	Register("play", parseCode)
}

type Code struct {
	Text template.HTML
	Play bool // runnable code
}

func (c Code) TemplateName() string { return "code" }

// The input line is a .code or .play entry with a file name and an optional HLfoo marker on the end.
// Anything between the file and HL (if any) is an address expression, which we treat as a string here.
// We pick off the HL first, for easy parsing.
var highlightRE = regexp.MustCompile(`\s+HL([a-zA-Z0-9_]+)?$`)
var codeRE = regexp.MustCompile(`\.(code|play)\s+([^\s]+)(\s+)?(.*)?$`)

func parseCode(ctx *Context, sourceFile string, sourceLine int, cmd string) (Elem, error) {
	cmd = strings.TrimSpace(cmd)

	// Pull off the HL, if any, from the end of the input line.
	highlight := ""
	if hl := highlightRE.FindStringSubmatchIndex(cmd); len(hl) == 4 {
		highlight = cmd[hl[2]:hl[3]]
		cmd = cmd[:hl[2]-2]
	}

	// Parse the remaining command line.
	// Arguments:
	// args[0]: whole match
	// args[1]:  .code/.play
	// args[2]: file name
	// args[3]: space, if any, before optional address
	// args[4]: optional address
	args := codeRE.FindStringSubmatch(cmd)
	if len(args) != 5 {
		return nil, fmt.Errorf("%s:%d: syntax error for .code/.play invocation", sourceFile, sourceLine)
	}
	command, file, addr := args[1], args[2], strings.TrimSpace(args[4])
	play := command == "play" && PlayEnabled

	// Read in code file and (optionally) match address.
	filename := filepath.Join(filepath.Dir(sourceFile), file)
	textBytes, err := ctx.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("%s:%d: %v", sourceFile, sourceLine, err)
	}
	lo, hi, err := addrToByteRange(addr, 0, textBytes)
	if err != nil {
		return nil, fmt.Errorf("%s:%d: %v", sourceFile, sourceLine, err)
	}

	// Acme pattern matches stop mid-line,
	// so run to end of line in both directions.
	for lo > 0 && textBytes[lo-1] != '\n' {
		lo--
	}
	for hi < len(textBytes) {
		hi++
		if textBytes[hi-1] == '\n' {
			break
		}
	}
	text := string(textBytes[lo:hi])

	// Clear ommitted lines.
	text = skipOMIT(text)

	// Replace tabs by spaces, which work better in HTML.
	text = strings.Replace(text, "\t", "    ", -1)

	// Escape the program text for HTML.
	text = template.HTMLEscapeString(text)

	// Highlight and span-wrap lines.
	text = "
" + highlightLines(text, highlight) + "
"

	// Include before and after in a hidden span for playground code.
	if play {
		text = hide(skipOMIT(string(textBytes[:lo]))) +
			text + hide(skipOMIT(string(textBytes[hi:])))
	}

	// Include the command as a comment.
	text = fmt.Sprintf("%s", cmd, text)

	return Code{Text: template.HTML(text), Play: play}, nil
}

// skipOMIT turns text into a string, dropping lines ending with OMIT.
func skipOMIT(text string) string {
	lines := strings.SplitAfter(text, "\n")
	for k := range lines {
		if strings.HasSuffix(lines[k], "OMIT\n") {
			lines[k] = ""
		}
	}
	return strings.Join(lines, "")
}

func parseArgs(name string, line int, args []string) (res []interface{}, err error) {
	res = make([]interface{}, len(args))
	for i, v := range args {
		if len(v) == 0 {
			return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
		}
		switch v[0] {
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
			n, err := strconv.Atoi(v)
			if err != nil {
				return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
			}
			res[i] = n
		case '/':
			if len(v) < 2 || v[len(v)-1] != '/' {
				return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
			}
			res[i] = v
		case '$':
			res[i] = "$"
		default:
			return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
		}
	}
	return
}

// parseArg returns the integer or string value of the argument and tells which it is.
func parseArg(arg interface{}, file string, max int) (ival int, sval string, isInt bool) {
	switch n := arg.(type) {
	case int:
		if n <= 0 || n > max {
			log.Fatalf("%q:%d is out of range", file, n)
		}
		return n, "", true
	case string:
		return 0, n, false
	}
	log.Fatalf("unrecognized argument %v type %T", arg, arg)
	return
}

// oneLine returns the single line generated by a two-argument code invocation.
func oneLine(ctx *Context, file, text string, arg interface{}) (line, before, after string, err error) {
	contentBytes, err := ctx.ReadFile(file)
	if err != nil {
		return "", "", "", err
	}
	lines := strings.SplitAfter(string(contentBytes), "\n")
	lineNum, pattern, isInt := parseArg(arg, file, len(lines))
	var n int
	if isInt {
		n = lineNum - 1
	} else {
		n, err = match(file, 0, lines, pattern)
		n -= 1
	}
	if err != nil {
		return "", "", "", err
	}
	return lines[n],
		strings.Join(lines[:n], ""),
		strings.Join(lines[n+1:], ""),
		nil
}

// multipleLines returns the text generated by a three-argument code invocation.
func multipleLines(ctx *Context, file string, arg1, arg2 interface{}) (line, before, after string, err error) {
	contentBytes, err := ctx.ReadFile(file)
	lines := strings.SplitAfter(string(contentBytes), "\n")
	if err != nil {
		return "", "", "", err
	}
	line1, pattern1, isInt1 := parseArg(arg1, file, len(lines))
	line2, pattern2, isInt2 := parseArg(arg2, file, len(lines))
	if !isInt1 {
		line1, err = match(file, 0, lines, pattern1)
	}
	if !isInt2 {
		line2, err = match(file, line1, lines, pattern2)
	} else if line2 < line1 {
		return "", "", "", fmt.Errorf("lines out of order for %q: %d %d", file, line1, line2)
	}
	if err != nil {
		return "", "", "", err
	}
	for k := line1 - 1; k < line2; k++ {
		if strings.HasSuffix(lines[k], "OMIT\n") {
			lines[k] = ""
		}
	}
	return strings.Join(lines[line1-1:line2], ""),
		strings.Join(lines[:line1-1], ""),
		strings.Join(lines[line2:], ""),
		nil
}

// match identifies the input line that matches the pattern in a code invocation.
// If start>0, match lines starting there rather than at the beginning.
// The return value is 1-indexed.
func match(file string, start int, lines []string, pattern string) (int, error) {
	// $ matches the end of the file.
	if pattern == "$" {
		if len(lines) == 0 {
			return 0, fmt.Errorf("%q: empty file", file)
		}
		return len(lines), nil
	}
	// /regexp/ matches the line that matches the regexp.
	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
		re, err := regexp.Compile(pattern[1 : len(pattern)-1])
		if err != nil {
			return 0, err
		}
		for i := start; i < len(lines); i++ {
			if re.MatchString(lines[i]) {
				return i + 1, nil
			}
		}
		return 0, fmt.Errorf("%s: no match for %#q", file, pattern)
	}
	return 0, fmt.Errorf("unrecognized pattern: %q", pattern)
}

var hlRE = regexp.MustCompile(`(.+) // HL(.*)$`)

// highlightLines emboldens lines that end with "// HL" and
// wraps any other lines in span tags.
func highlightLines(text, label string) string {
	lines := strings.Split(text, "\n")
	for i, line := range lines {
		m := hlRE.FindStringSubmatch(line)
		if m == nil {
			continue
		}
		line := m[1]
		if m[2] != "" && m[2] != label {
			lines[i] = line
			continue
		}
		space := ""
		if j := strings.IndexFunc(line, func(r rune) bool {
			return !unicode.IsSpace(r)
		}); j > 0 {
			space = line[:j]
			line = line[j:]
		}
		lines[i] = space + "" + line + ""
	}
	return strings.Join(lines, "\n")
}

func hide(text string) string {
	return fmt.Sprintf(`<pre style="display: none">%s</pre>`, template.HTMLEscapeString(text))
}
<commit_msg>go.talks/pkg/present: remove remaining log.Fatal calls<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package present

import (
	"fmt"
	"html/template"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"unicode"
)

// Is the playground available?
var PlayEnabled = false

// TOOD(adg): replace the PlayEnabled flag with something less spaghetti-like.
// Instead this will probably be determined by a template execution Context
// value that contains various global metadata required when rendering
// templates.

func init() {
	Register("code", parseCode)
	Register("play", parseCode)
}

type Code struct {
	Text template.HTML
	Play bool // runnable code
}

func (c Code) TemplateName() string { return "code" }

// The input line is a .code or .play entry with a file name and an optional HLfoo marker on the end.
// Anything between the file and HL (if any) is an address expression, which we treat as a string here.
// We pick off the HL first, for easy parsing.
var highlightRE = regexp.MustCompile(`\s+HL([a-zA-Z0-9_]+)?$`)
var codeRE = regexp.MustCompile(`\.(code|play)\s+([^\s]+)(\s+)?(.*)?$`)

func parseCode(ctx *Context, sourceFile string, sourceLine int, cmd string) (Elem, error) {
	cmd = strings.TrimSpace(cmd)

	// Pull off the HL, if any, from the end of the input line.
	highlight := ""
	if hl := highlightRE.FindStringSubmatchIndex(cmd); len(hl) == 4 {
		highlight = cmd[hl[2]:hl[3]]
		cmd = cmd[:hl[2]-2]
	}

	// Parse the remaining command line.
	// Arguments:
	// args[0]: whole match
	// args[1]:  .code/.play
	// args[2]: file name
	// args[3]: space, if any, before optional address
	// args[4]: optional address
	args := codeRE.FindStringSubmatch(cmd)
	if len(args) != 5 {
		return nil, fmt.Errorf("%s:%d: syntax error for .code/.play invocation", sourceFile, sourceLine)
	}
	command, file, addr := args[1], args[2], strings.TrimSpace(args[4])
	play := command == "play" && PlayEnabled

	// Read in code file and (optionally) match address.
	filename := filepath.Join(filepath.Dir(sourceFile), file)
	textBytes, err := ctx.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("%s:%d: %v", sourceFile, sourceLine, err)
	}
	lo, hi, err := addrToByteRange(addr, 0, textBytes)
	if err != nil {
		return nil, fmt.Errorf("%s:%d: %v", sourceFile, sourceLine, err)
	}

	// Acme pattern matches stop mid-line,
	// so run to end of line in both directions.
	for lo > 0 && textBytes[lo-1] != '\n' {
		lo--
	}
	for hi < len(textBytes) {
		hi++
		if textBytes[hi-1] == '\n' {
			break
		}
	}
	text := string(textBytes[lo:hi])

	// Clear ommitted lines.
	text = skipOMIT(text)

	// Replace tabs by spaces, which work better in HTML.
	text = strings.Replace(text, "\t", "    ", -1)

	// Escape the program text for HTML.
	text = template.HTMLEscapeString(text)

	// Highlight and span-wrap lines.
	text = "
" + highlightLines(text, highlight) + "
"

	// Include before and after in a hidden span for playground code.
	if play {
		text = hide(skipOMIT(string(textBytes[:lo]))) +
			text + hide(skipOMIT(string(textBytes[hi:])))
	}

	// Include the command as a comment.
	text = fmt.Sprintf("%s", cmd, text)

	return Code{Text: template.HTML(text), Play: play}, nil
}

// skipOMIT turns text into a string, dropping lines ending with OMIT.
func skipOMIT(text string) string {
	lines := strings.SplitAfter(text, "\n")
	for k := range lines {
		if strings.HasSuffix(lines[k], "OMIT\n") {
			lines[k] = ""
		}
	}
	return strings.Join(lines, "")
}

func parseArgs(name string, line int, args []string) (res []interface{}, err error) {
	res = make([]interface{}, len(args))
	for i, v := range args {
		if len(v) == 0 {
			return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
		}
		switch v[0] {
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
			n, err := strconv.Atoi(v)
			if err != nil {
				return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
			}
			res[i] = n
		case '/':
			if len(v) < 2 || v[len(v)-1] != '/' {
				return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
			}
			res[i] = v
		case '$':
			res[i] = "$"
		default:
			return nil, fmt.Errorf("%s:%d bad code argument %q", name, line, v)
		}
	}
	return
}

// parseArg returns the integer or string value of the argument and tells which it is.
func parseArg(arg interface{}, max int) (ival int, sval string, isInt bool, err error) {
	switch n := arg.(type) {
	case int:
		if n <= 0 || n > max {
			return 0, "", false, fmt.Errorf("%%d is out of range", n)
		}
		return n, "", true, nil
	case string:
		return 0, n, false, nil
	}
	return 0, "", false, fmt.Errorf("unrecognized argument %v type %T", arg, arg)
}

// oneLine returns the single line generated by a two-argument code invocation.
func oneLine(ctx *Context, file, text string, arg interface{}) (line, before, after string, err error) {
	contentBytes, err := ctx.ReadFile(file)
	if err != nil {
		return "", "", "", err
	}
	lines := strings.SplitAfter(string(contentBytes), "\n")
	lineNum, pattern, isInt, err := parseArg(arg, len(lines))
	if err != nil {
		return "", "", "", err
	}
	var n int
	if isInt {
		n = lineNum - 1
	} else {
		n, err = match(file, 0, lines, pattern)
		n -= 1
	}
	if err != nil {
		return "", "", "", err
	}
	return lines[n],
		strings.Join(lines[:n], ""),
		strings.Join(lines[n+1:], ""),
		nil
}

// multipleLines returns the text generated by a three-argument code invocation.
func multipleLines(ctx *Context, file string, arg1, arg2 interface{}) (line, before, after string, err error) {
	contentBytes, err := ctx.ReadFile(file)
	lines := strings.SplitAfter(string(contentBytes), "\n")
	if err != nil {
		return "", "", "", err
	}
	line1, pattern1, isInt1, err := parseArg(arg1, len(lines))
	if err != nil {
		return "", "", "", err
	}
	line2, pattern2, isInt2, err := parseArg(arg2, len(lines))
	if err != nil {
		return "", "", "", err
	}
	if !isInt1 {
		line1, err = match(file, 0, lines, pattern1)
	}
	if !isInt2 {
		line2, err = match(file, line1, lines, pattern2)
	} else if line2 < line1 {
		return "", "", "", fmt.Errorf("lines out of order for %q: %d %d", file, line1, line2)
	}
	if err != nil {
		return "", "", "", err
	}
	for k := line1 - 1; k < line2; k++ {
		if strings.HasSuffix(lines[k], "OMIT\n") {
			lines[k] = ""
		}
	}
	return strings.Join(lines[line1-1:line2], ""),
		strings.Join(lines[:line1-1], ""),
		strings.Join(lines[line2:], ""),
		nil
}

// match identifies the input line that matches the pattern in a code invocation.
// If start>0, match lines starting there rather than at the beginning.
// The return value is 1-indexed.
func match(file string, start int, lines []string, pattern string) (int, error) {
	// $ matches the end of the file.
	if pattern == "$" {
		if len(lines) == 0 {
			return 0, fmt.Errorf("%q: empty file", file)
		}
		return len(lines), nil
	}
	// /regexp/ matches the line that matches the regexp.
	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
		re, err := regexp.Compile(pattern[1 : len(pattern)-1])
		if err != nil {
			return 0, err
		}
		for i := start; i < len(lines); i++ {
			if re.MatchString(lines[i]) {
				return i + 1, nil
			}
		}
		return 0, fmt.Errorf("%s: no match for %#q", file, pattern)
	}
	return 0, fmt.Errorf("unrecognized pattern: %q", pattern)
}

var hlRE = regexp.MustCompile(`(.+) // HL(.*)$`)

// highlightLines emboldens lines that end with "// HL" and
// wraps any other lines in span tags.
func highlightLines(text, label string) string {
	lines := strings.Split(text, "\n")
	for i, line := range lines {
		m := hlRE.FindStringSubmatch(line)
		if m == nil {
			continue
		}
		line := m[1]
		if m[2] != "" && m[2] != label {
			lines[i] = line
			continue
		}
		space := ""
		if j := strings.IndexFunc(line, func(r rune) bool {
			return !unicode.IsSpace(r)
		}); j > 0 {
			space = line[:j]
			line = line[j:]
		}
		lines[i] = space + "" + line + ""
	}
	return strings.Join(lines, "\n")
}

func hide(text string) string {
	return fmt.Sprintf(`<pre style="display: none">%s</pre>`, template.HTMLEscapeString(text))
}
<|endoftext|>


<commit_before>// Copyright 2016 The etcd-operator 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 spec

import (
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
)

type EtcdCluster struct {
	unversioned.TypeMeta `json:",inline"`
	api.ObjectMeta       `json:"metadata,omitempty"`
	Spec                 ClusterSpec `json:"spec"`
}

type ClusterSpec struct {
	// Size is the expected size of the etcd cluster.
	// The etcd-operator will eventually make the size of the running
	// cluster equal to the expected size.
	// The vaild range of the size is from 1 to 7.
	Size int `json:"size"`

	// Version is the expected version of the etcd cluster.
	// The etcd-operator will eventually make the etcd cluster version
	// equal to the expected version.
	Version string `json:"version"`

	// Backup is the backup policy for the etcd cluster.
	// There is no backup by default.
	Backup *BackupPolicy `json:"backup,omitempty"`

	// Paused is to pause the control of the operator for the etcd cluster.
	Paused bool `json:"paused,omitempty"`

	// NodeSelector specifies a map of key-value pairs. For the pod to be eligible
	// to run on a node, the node must have each of the indicated key-value pairs as
	// labels.
	NodeSelector map[string]string `json:"nodeSelector,omitempty"`

	// AntiAffinity determines if the etcd-operator tries to avoid putting
	// the etcd members in the same cluster onto the same node.
	AntiAffinity bool `json:"antiAffinity"`

	// SelfHosted determines if the etcd cluster is used for a self-hosted
	// Kubernetes cluster.
	SelfHosted *SelfHostedPolicy `json:"selfHosted,omitempty"`
}

type SeedPolicy struct {
	// The client endpoints of the seed member.
	MemberClientEndpoints []string
	// RemoveDelay specifies the delay to remove the original seed member from the
	// cluster in seconds.
	// The seed member will be removed in 30 second by default. Minimum delay is 10 seconds.
	RemoveDelay int
}
<commit_msg>spec: remove legacy seed policy<commit_after>// Copyright 2016 The etcd-operator 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 spec

import (
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
)

type EtcdCluster struct {
	unversioned.TypeMeta `json:",inline"`
	api.ObjectMeta       `json:"metadata,omitempty"`
	Spec                 ClusterSpec `json:"spec"`
}

type ClusterSpec struct {
	// Size is the expected size of the etcd cluster.
	// The etcd-operator will eventually make the size of the running
	// cluster equal to the expected size.
	// The vaild range of the size is from 1 to 7.
	Size int `json:"size"`

	// Version is the expected version of the etcd cluster.
	// The etcd-operator will eventually make the etcd cluster version
	// equal to the expected version.
	Version string `json:"version"`

	// Backup is the backup policy for the etcd cluster.
	// There is no backup by default.
	Backup *BackupPolicy `json:"backup,omitempty"`

	// Paused is to pause the control of the operator for the etcd cluster.
	Paused bool `json:"paused,omitempty"`

	// NodeSelector specifies a map of key-value pairs. For the pod to be eligible
	// to run on a node, the node must have each of the indicated key-value pairs as
	// labels.
	NodeSelector map[string]string `json:"nodeSelector,omitempty"`

	// AntiAffinity determines if the etcd-operator tries to avoid putting
	// the etcd members in the same cluster onto the same node.
	AntiAffinity bool `json:"antiAffinity"`

	// SelfHosted determines if the etcd cluster is used for a self-hosted
	// Kubernetes cluster.
	SelfHosted *SelfHostedPolicy `json:"selfHosted,omitempty"`
}
<|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 cert

import (
	"crypto/x509"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
)

// CanReadCertAndKey returns true if the certificate and key files already exists,
// otherwise returns false. If lost one of cert and key, returns error.
func CanReadCertAndKey(certPath, keyPath string) (bool, error) {
	certReadable := canReadFile(certPath)
	keyReadable := canReadFile(keyPath)

	if certReadable == false && keyReadable == false {
		return false, nil
	}

	if certReadable == false {
		return false, fmt.Errorf("error reading %s, certificate and key must be supplied as a pair", certPath)
	}

	if keyReadable == false {
		return false, fmt.Errorf("error reading %s, certificate and key must be supplied as a pair", keyPath)
	}

	return true, nil
}

// If the file represented by path exists and
// readable, returns true otherwise returns false.
func canReadFile(path string) bool {
	f, err := os.Open(path)
	if err != nil {
		return false
	}

	defer f.Close()

	return true
}

// WriteCert writes the pem-encoded certificate data to certPath.
// The certificate file will be created with file mode 0644.
// If the certificate file already exists, it will be overwritten.
// The parent directory of the certPath will be created as needed with file mode 0755.
func WriteCert(certPath string, data []byte) error {
	if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil {
		return err
	}
	if err := ioutil.WriteFile(certPath, data, os.FileMode(0644)); err != nil {
		return err
	}
	return nil
}

// WriteKey writes the pem-encoded key data to keyPath.
// The key file will be created with file mode 0600.
// If the key file already exists, it will be overwritten.
// The parent directory of the keyPath will be created as needed with file mode 0755.
func WriteKey(keyPath string, data []byte) error {
	if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil {
		return err
	}
	if err := ioutil.WriteFile(keyPath, data, os.FileMode(0600)); err != nil {
		return err
	}
	return nil
}

// NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file.
// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
func NewPool(filename string) (*x509.CertPool, error) {
	certs, err := CertsFromFile(filename)
	if err != nil {
		return nil, err
	}
	pool := x509.NewCertPool()
	for _, cert := range certs {
		pool.AddCert(cert)
	}
	return pool, nil
}

// CertsFromFile returns the x509.Certificates contained in the given PEM-encoded file.
// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
func CertsFromFile(file string) ([]*x509.Certificate, error) {
	if len(file) == 0 {
		return nil, errors.New("error reading certificates from an empty filename")
	}
	pemBlock, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	certs, err := ParseCertsPEM(pemBlock)
	if err != nil {
		return nil, fmt.Errorf("error reading %s: %s", file, err)
	}
	return certs, nil
}
<commit_msg>Add a PrivateKeyFromFile method to certutil for parsing a private key from a file<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 cert

import (
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
)

// CanReadCertAndKey returns true if the certificate and key files already exists,
// otherwise returns false. If lost one of cert and key, returns error.
func CanReadCertAndKey(certPath, keyPath string) (bool, error) {
	certReadable := canReadFile(certPath)
	keyReadable := canReadFile(keyPath)

	if certReadable == false && keyReadable == false {
		return false, nil
	}

	if certReadable == false {
		return false, fmt.Errorf("error reading %s, certificate and key must be supplied as a pair", certPath)
	}

	if keyReadable == false {
		return false, fmt.Errorf("error reading %s, certificate and key must be supplied as a pair", keyPath)
	}

	return true, nil
}

// If the file represented by path exists and
// readable, returns true otherwise returns false.
func canReadFile(path string) bool {
	f, err := os.Open(path)
	if err != nil {
		return false
	}

	defer f.Close()

	return true
}

// WriteCert writes the pem-encoded certificate data to certPath.
// The certificate file will be created with file mode 0644.
// If the certificate file already exists, it will be overwritten.
// The parent directory of the certPath will be created as needed with file mode 0755.
func WriteCert(certPath string, data []byte) error {
	if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil {
		return err
	}
	if err := ioutil.WriteFile(certPath, data, os.FileMode(0644)); err != nil {
		return err
	}
	return nil
}

// WriteKey writes the pem-encoded key data to keyPath.
// The key file will be created with file mode 0600.
// If the key file already exists, it will be overwritten.
// The parent directory of the keyPath will be created as needed with file mode 0755.
func WriteKey(keyPath string, data []byte) error {
	if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil {
		return err
	}
	if err := ioutil.WriteFile(keyPath, data, os.FileMode(0600)); err != nil {
		return err
	}
	return nil
}

// NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file.
// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
func NewPool(filename string) (*x509.CertPool, error) {
	certs, err := CertsFromFile(filename)
	if err != nil {
		return nil, err
	}
	pool := x509.NewCertPool()
	for _, cert := range certs {
		pool.AddCert(cert)
	}
	return pool, nil
}

// CertsFromFile returns the x509.Certificates contained in the given PEM-encoded file.
// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
func CertsFromFile(file string) ([]*x509.Certificate, error) {
	pemBlock, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	certs, err := ParseCertsPEM(pemBlock)
	if err != nil {
		return nil, fmt.Errorf("error reading %s: %s", file, err)
	}
	return certs, nil
}

// PrivateKeyFromFile returns the private key in rsa.PrivateKey or ecdsa.PrivateKey format from a given PEM-encoded file.
// Returns an error if the file could not be read or if the private key could not be parsed.
func PrivateKeyFromFile(file string) (interface{}, error) {
	pemBlock, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	key, err := ParsePrivateKeyPEM(pemBlock)
	if err != nil {
		return nil, fmt.Errorf("error reading %s: %v", file, err)
	}
	return key, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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

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

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

package 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.
//
// The "-dev" suffix in the version info indicates that fact, and it means the
// current build is from a version greater that version. For example, v0.7-dev
// means version > 0.7 and < 0.8. (There's exceptions to this rule, see
// docs/releasing.md for more details.)
//
// When releasing a new Kubernetes version, this file should be updated to
// reflect the new version, and then a git annotated tag (using format vX.Y
// where X == Major version and Y == Minor version) should be created to point
// to the commit that updates pkg/version/base.go

var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead.
	gitMajor     string = "0"              // major version, always numeric
	gitMinor     string = "17.1+"          // minor version, numeric possibly followed by "+"
	gitVersion   string = "v0.17.1-dev"    // version from git, output of $(git describe)
	gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
)
<commit_msg>Kubernetes version v0.18.0<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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

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

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

package 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.
//
// The "-dev" suffix in the version info indicates that fact, and it means the
// current build is from a version greater that version. For example, v0.7-dev
// means version > 0.7 and < 0.8. (There's exceptions to this rule, see
// docs/releasing.md for more details.)
//
// When releasing a new Kubernetes version, this file should be updated to
// reflect the new version, and then a git annotated tag (using format vX.Y
// where X == Major version and Y == Minor version) should be created to point
// to the commit that updates pkg/version/base.go

var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead.
	gitMajor     string = "0"              // major version, always numeric
	gitMinor     string = "18.0"           // minor version, numeric possibly followed by "+"
	gitVersion   string = "v0.18.0"        // version from git, output of $(git describe)
	gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
)
<|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-tools/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 = "5" // 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.5.0+$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.5.1-beta.0<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-tools/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 = "5+" // 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.5.1-beta.0+$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|>