<commit_before>package http

import (
	"fmt"

	"github.com/golang/glog"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/selection"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"

	"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
)

func podLabels(crt *v1alpha1.Certificate, domain string) map[string]string {
	return map[string]string{
		certNameLabelKey: crt.Name,
		domainLabelKey:   domain,
	}
}

func (s *Solver) ensurePod(crt *v1alpha1.Certificate, domain, token, key string) (*corev1.Pod, error) {
	existingPods, err := s.getPodsForCertificate(crt, domain)
	if err != nil {
		return nil, err
	}
	if len(existingPods) == 1 {
		return existingPods[0], nil
	}
	if len(existingPods) > 1 {
		errMsg := fmt.Sprintf("multiple challenge solver pods found for certificate '%s/%s'. Cleaning up existing pods.", crt.Namespace, crt.Name)
		glog.Infof(errMsg)
		err := s.cleanupPods(crt, domain)
		if err != nil {
			return nil, err
		}
		return nil, fmt.Errorf(errMsg)
	}

	glog.Infof("No existing HTTP01 challenge solver pod found for Certificate %q. One will be created.", crt.Name)
	return s.createPod(crt, domain, token, key)
}

// getPodsForCertificate returns a list of pods that were created to solve
// http challenges for the given domain
func (s *Solver) getPodsForCertificate(crt *v1alpha1.Certificate, domain string) ([]*corev1.Pod, error) {
	podLabels := podLabels(crt, domain)
	orderSelector := labels.NewSelector()
	for key, val := range podLabels {
		req, err := labels.NewRequirement(key, selection.Equals, []string{val})
		if err != nil {
			return nil, err
		}
		orderSelector = orderSelector.Add(*req)
	}

	podList, err := s.podLister.Pods(crt.Namespace).List(orderSelector)
	if err != nil {
		return nil, err
	}

	var relevantPods []*corev1.Pod
	for _, pod := range podList {
		if !metav1.IsControlledBy(pod, crt) {
			glog.Infof("Found pod %q with acme-order-url annotation set to that of Certificate %q"+
				"but it is not owned by the Certificate resource, so skipping it.", pod.Name, crt.Name)
			continue
		}
		relevantPods = append(relevantPods, pod)
	}

	return relevantPods, nil
}

func (s *Solver) cleanupPods(crt *v1alpha1.Certificate, domain string) error {
	pods, err := s.getPodsForCertificate(crt, domain)
	if err != nil {
		return err
	}
	var errs []error
	for _, pod := range pods {
		// TODO: should we call DeleteCollection here? We'd need to somehow
		// also ensure ownership as part of that request using a FieldSelector.
		err := s.client.CoreV1().Pods(pod.Namespace).Delete(pod.Name, nil)
		if err != nil {
			errs = append(errs, err)
		}
	}
	return utilerrors.NewAggregate(errs)
}

// createPod will create a challenge solving pod for the given certificate,
// domain, token and key.
func (s *Solver) createPod(crt *v1alpha1.Certificate, domain, token, key string) (*corev1.Pod, error) {
	return s.client.CoreV1().Pods(crt.Namespace).Create(s.buildPod(crt, domain, token, key))
}

// buildPod will build a challenge solving pod for the given certificate,
// domain, token and key. It will not create it in the API server
func (s *Solver) buildPod(crt *v1alpha1.Certificate, domain, token, key string) *corev1.Pod {
	podLabels := podLabels(crt, domain)
	return &corev1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName:    "cm-acme-http-solver-",
			Namespace:       crt.Namespace,
			Labels:          podLabels,
			OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(crt, certificateGvk)},
		},
		Spec: corev1.PodSpec{
			RestartPolicy: corev1.RestartPolicyOnFailure,
			Containers: []corev1.Container{
				{
					Name: "acmesolver",
					// TODO: use an image as specified as a config option
					Image:           s.solverImage,
					ImagePullPolicy: corev1.PullIfNotPresent,
					// TODO: replace this with some kind of cmdline generator
					Args: []string{
						fmt.Sprintf("--listen-port=%d", acmeSolverListenPort),
						fmt.Sprintf("--domain=%s", domain),
						fmt.Sprintf("--token=%s", token),
						fmt.Sprintf("--key=%s", key),
					},
					Resources: corev1.ResourceRequirements{
						Requests: corev1.ResourceList{
							corev1.ResourceCPU:    resource.MustParse("10m"),
							corev1.ResourceMemory: resource.MustParse("64Mi"),
						},
						Limits: corev1.ResourceList{
							corev1.ResourceCPU:    resource.MustParse("10m"),
							corev1.ResourceMemory: resource.MustParse("64Mi"),
						},
					},
					Ports: []corev1.ContainerPort{
						{
							Name:          "http",
							ContainerPort: acmeSolverListenPort,
						},
					},
				},
			},
		},
	}
}
<commit_msg>Add TODO for domain label values<commit_after>package http

import (
	"fmt"

	"github.com/golang/glog"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/selection"
	utilerrors "k8s.io/apimachinery/pkg/util/errors"

	"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
)

func podLabels(crt *v1alpha1.Certificate, domain string) map[string]string {
	return map[string]string{
		certNameLabelKey: crt.Name,
		// TODO: we need to support domains longer than 63 characters
		// this value should probably be hashed, and then the full plain text
		// value stored as an annotation to make it easier for users to read
		// see #425 for details: https://github.com/jetstack/cert-manager/issues/425
		domainLabelKey: domain,
	}
}

func (s *Solver) ensurePod(crt *v1alpha1.Certificate, domain, token, key string) (*corev1.Pod, error) {
	existingPods, err := s.getPodsForCertificate(crt, domain)
	if err != nil {
		return nil, err
	}
	if len(existingPods) == 1 {
		return existingPods[0], nil
	}
	if len(existingPods) > 1 {
		errMsg := fmt.Sprintf("multiple challenge solver pods found for certificate '%s/%s'. Cleaning up existing pods.", crt.Namespace, crt.Name)
		glog.Infof(errMsg)
		err := s.cleanupPods(crt, domain)
		if err != nil {
			return nil, err
		}
		return nil, fmt.Errorf(errMsg)
	}

	glog.Infof("No existing HTTP01 challenge solver pod found for Certificate %q. One will be created.", crt.Name)
	return s.createPod(crt, domain, token, key)
}

// getPodsForCertificate returns a list of pods that were created to solve
// http challenges for the given domain
func (s *Solver) getPodsForCertificate(crt *v1alpha1.Certificate, domain string) ([]*corev1.Pod, error) {
	podLabels := podLabels(crt, domain)
	orderSelector := labels.NewSelector()
	for key, val := range podLabels {
		req, err := labels.NewRequirement(key, selection.Equals, []string{val})
		if err != nil {
			return nil, err
		}
		orderSelector = orderSelector.Add(*req)
	}

	podList, err := s.podLister.Pods(crt.Namespace).List(orderSelector)
	if err != nil {
		return nil, err
	}

	var relevantPods []*corev1.Pod
	for _, pod := range podList {
		if !metav1.IsControlledBy(pod, crt) {
			glog.Infof("Found pod %q with acme-order-url annotation set to that of Certificate %q"+
				"but it is not owned by the Certificate resource, so skipping it.", pod.Name, crt.Name)
			continue
		}
		relevantPods = append(relevantPods, pod)
	}

	return relevantPods, nil
}

func (s *Solver) cleanupPods(crt *v1alpha1.Certificate, domain string) error {
	pods, err := s.getPodsForCertificate(crt, domain)
	if err != nil {
		return err
	}
	var errs []error
	for _, pod := range pods {
		// TODO: should we call DeleteCollection here? We'd need to somehow
		// also ensure ownership as part of that request using a FieldSelector.
		err := s.client.CoreV1().Pods(pod.Namespace).Delete(pod.Name, nil)
		if err != nil {
			errs = append(errs, err)
		}
	}
	return utilerrors.NewAggregate(errs)
}

// createPod will create a challenge solving pod for the given certificate,
// domain, token and key.
func (s *Solver) createPod(crt *v1alpha1.Certificate, domain, token, key string) (*corev1.Pod, error) {
	return s.client.CoreV1().Pods(crt.Namespace).Create(s.buildPod(crt, domain, token, key))
}

// buildPod will build a challenge solving pod for the given certificate,
// domain, token and key. It will not create it in the API server
func (s *Solver) buildPod(crt *v1alpha1.Certificate, domain, token, key string) *corev1.Pod {
	podLabels := podLabels(crt, domain)
	return &corev1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName:    "cm-acme-http-solver-",
			Namespace:       crt.Namespace,
			Labels:          podLabels,
			OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(crt, certificateGvk)},
		},
		Spec: corev1.PodSpec{
			RestartPolicy: corev1.RestartPolicyOnFailure,
			Containers: []corev1.Container{
				{
					Name: "acmesolver",
					// TODO: use an image as specified as a config option
					Image:           s.solverImage,
					ImagePullPolicy: corev1.PullIfNotPresent,
					// TODO: replace this with some kind of cmdline generator
					Args: []string{
						fmt.Sprintf("--listen-port=%d", acmeSolverListenPort),
						fmt.Sprintf("--domain=%s", domain),
						fmt.Sprintf("--token=%s", token),
						fmt.Sprintf("--key=%s", key),
					},
					Resources: corev1.ResourceRequirements{
						Requests: corev1.ResourceList{
							corev1.ResourceCPU:    resource.MustParse("10m"),
							corev1.ResourceMemory: resource.MustParse("64Mi"),
						},
						Limits: corev1.ResourceList{
							corev1.ResourceCPU:    resource.MustParse("10m"),
							corev1.ResourceMemory: resource.MustParse("64Mi"),
						},
					},
					Ports: []corev1.ContainerPort{
						{
							Name:          "http",
							ContainerPort: acmeSolverListenPort,
						},
					},
				},
			},
		},
	}
}
<|endoftext|>


<commit_before>package kubeconfig

import "html/template"

const (
	tokenTemplateText = `apiVersion: v1
kind: Config
clusters:
{{- range .Nodes}}
- name: "{{.ClusterName}}"
  cluster:
    server: "{{.Server}}"
{{- if ne .Cert "" }}
    certificate-authority-data: "{{.Cert}}"
{{- end }}
{{- end}}

users:
- name: "{{.ClusterName}}"
  user:
    token: "{{.Token}}"

contexts:
{{- range .Nodes}}
- name: "{{.ClusterName}}"
  context:
    user: "{{.ClusterName}}"
    cluster: "{{.ClusterName}}"
{{- end}}

current-context: "{{.ClusterName}}"
`

	basicTemplateText = `apiVersion: v1
kind: Config
clusters:
- name: "{{.ClusterName}}"
  cluster:
    server: "https://{{.Host}}"
    api-version: v1

users:
- name: "{{.ClusterName}}"
  user:
    username: "{{.Username}}"
    password: "{{.Password}}"

contexts:
- name: "{{.ClusterName}}"
  context:
    user: "{{.ClusterName}}"
    cluster: "{{.ClusterName}}"

current-context: "{{.ClusterName}}"
`
)

var (
	basicTemplate = template.Must(template.New("basicTemplate").Parse(basicTemplateText))
	tokenTemplate = template.Must(template.New("tokenTemplate").Parse(tokenTemplateText))
)
<commit_msg>Revert "Use ClusterName for KubeConfig User's name"<commit_after>package kubeconfig

import "html/template"

const (
	tokenTemplateText = `apiVersion: v1
kind: Config
clusters:
{{- range .Nodes}}
- name: "{{.ClusterName}}"
  cluster:
    server: "{{.Server}}"
{{- if ne .Cert "" }}
    certificate-authority-data: "{{.Cert}}"
{{- end }}
{{- end}}

users:
- name: "{{.User}}"
  user:
    token: "{{.Token}}"

contexts:
{{- range .Nodes}}
- name: "{{.ClusterName}}"
  context:
    user: "{{.User}}"
    cluster: "{{.ClusterName}}"
{{- end}}

current-context: "{{.ClusterName}}"
`

	basicTemplateText = `apiVersion: v1
kind: Config
clusters:
- name: "{{.ClusterName}}"
  cluster:
    server: "https://{{.Host}}"
    api-version: v1

users:
- name: "{{.User}}"
  user:
    username: "{{.Username}}"
    password: "{{.Password}}"

contexts:
- name: "{{.ClusterName}}"
  context:
    user: "{{.User}}"
    cluster: "{{.ClusterName}}"

current-context: "{{.ClusterName}}"
`
)

var (
	basicTemplate = template.Must(template.New("basicTemplate").Parse(basicTemplateText))
	tokenTemplate = template.Must(template.New("tokenTemplate").Parse(tokenTemplateText))
)
<|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 config

import (
	"fmt"

	"github.com/spf13/pflag"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ContainerRuntimeOptions defines options for the container runtime.
type ContainerRuntimeOptions struct {
	// General Options.

	// ContainerRuntime is the container runtime to use.
	ContainerRuntime string
	// RuntimeCgroups that container runtime is expected to be isolated in.
	RuntimeCgroups string

	// Docker-specific options.

	// DockershimRootDirectory is the path to the dockershim root directory. Defaults to
	// /var/lib/dockershim if unset. Exposed for integration testing (e.g. in OpenShift).
	DockershimRootDirectory string
	// PodSandboxImage is the image whose network/ipc namespaces
	// containers in each pod will use.
	PodSandboxImage string
	// DockerEndpoint is the path to the docker endpoint to communicate with.
	DockerEndpoint string
	// If no pulling progress is made before the deadline imagePullProgressDeadline,
	// the image pulling will be cancelled. Defaults to 1m0s.
	// +optional
	ImagePullProgressDeadline metav1.Duration

	// Network plugin options.

	// networkPluginName is the name of the network plugin to be invoked for
	// various events in kubelet/pod lifecycle
	NetworkPluginName string
	// NetworkPluginMTU is the MTU to be passed to the network plugin,
	// and overrides the default MTU for cases where it cannot be automatically
	// computed (such as IPSEC).
	NetworkPluginMTU int32
	// CNIConfDir is the full path of the directory in which to search for
	// CNI config files
	CNIConfDir string
	// CNIBinDir is the full path of the directory in which to search for
	// CNI plugin binaries
	CNIBinDir string
	// CNICacheDir is the full path of the directory in which CNI should store
	// cache files
	CNICacheDir string

	// Image credential provider plugin options

	// ImageCredentialProviderConfigFile is the path to the credential provider plugin config file.
	// This config file is a specification for what credential providers are enabled and invokved
	// by the kubelet. The plugin config should contain information about what plugin binary
	// to execute and what container images the plugin should be called for.
	// +optional
	ImageCredentialProviderConfigFile string
	// ImageCredentialProviderBinDir is the path to the directory where credential provider plugin
	// binaries exist. The name of each plugin binary is expected to match the name of the plugin
	// specified in imageCredentialProviderConfigFile.
	// +optional
	ImageCredentialProviderBinDir string
}

// AddFlags adds flags to the container runtime, according to ContainerRuntimeOptions.
func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) {
	dockerOnlyWarning := "This docker-specific flag only works when container-runtime is set to docker."

	// General settings.
	fs.StringVar(&s.ContainerRuntime, "container-runtime", s.ContainerRuntime, "The container runtime to use. Possible values: 'docker', 'remote'.")
	fs.StringVar(&s.RuntimeCgroups, "runtime-cgroups", s.RuntimeCgroups, "Optional absolute name of cgroups to create and run the runtime in.")
	_ = fs.Bool("redirect-container-streaming", false, "[REMOVED]") // TODO: Delete in v1.22
	fs.MarkDeprecated("redirect-container-streaming", "Container streaming redirection has been removed from the kubelet as of v1.20, and this flag will be removed in v1.22. For more details, see http://git.k8s.io/enhancements/keps/sig-node/20191205-container-streaming-requests.md")

	// Docker-specific settings.
	fs.StringVar(&s.DockershimRootDirectory, "experimental-dockershim-root-directory", s.DockershimRootDirectory, "Path to the dockershim root directory.")
	fs.MarkHidden("experimental-dockershim-root-directory")
	fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, fmt.Sprintf("Specified image will not be pruned by the image garbage collector. "+
		"When container-runtime is set to 'docker', all containers in each pod will use the network/ipc namespaces from this image. Other CRI implementations have their own configuration to set this image."))
	fs.StringVar(&s.DockerEndpoint, "docker-endpoint", s.DockerEndpoint, fmt.Sprintf("Use this for the docker endpoint to communicate with. %s", dockerOnlyWarning))
	fs.MarkDeprecated("docker-endpoint", "will be removed along with dockershim.")
	fs.DurationVar(&s.ImagePullProgressDeadline.Duration, "image-pull-progress-deadline", s.ImagePullProgressDeadline.Duration, fmt.Sprintf("If no pulling progress is made before this deadline, the image pulling will be cancelled. %s", dockerOnlyWarning))
	fs.MarkDeprecated("image-pull-progress-deadline", "will be removed along with dockershim.")

	// Network plugin settings for Docker.
	fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, fmt.Sprintf("The name of the network plugin to be invoked for various events in kubelet/pod lifecycle. %s", dockerOnlyWarning))
	fs.MarkDeprecated("network-plugin", "will be removed along with dockershim.")
	fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, fmt.Sprintf("The full path of the directory in which to search for CNI config files. %s", dockerOnlyWarning))
	fs.MarkDeprecated("cni-conf-dir", "will be removed along with dockershim.")
	fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, fmt.Sprintf("A comma-separated list of full paths of directories in which to search for CNI plugin binaries. %s", dockerOnlyWarning))
	fs.MarkDeprecated("cni-bin-dir", "will be removed along with dockershim.")
	fs.StringVar(&s.CNICacheDir, "cni-cache-dir", s.CNICacheDir, fmt.Sprintf("The full path of the directory in which CNI should store cache files. %s", dockerOnlyWarning))
	fs.MarkDeprecated("cni-cache-dir", "will be removed along with dockershim.")
	fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, fmt.Sprintf("The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU. %s", dockerOnlyWarning))
	fs.MarkDeprecated("network-plugin-mtu", "will be removed along with dockershim.")

	// Image credential provider settings.
	fs.StringVar(&s.ImageCredentialProviderConfigFile, "image-credential-provider-config", s.ImageCredentialProviderConfigFile, "The path to the credential provider plugin config file.")
	fs.StringVar(&s.ImageCredentialProviderBinDir, "image-credential-provider-bin-dir", s.ImageCredentialProviderBinDir, "The path to the directory where credential provider plugin binaries are located.")
}
<commit_msg>Fixed the broken link<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 config

import (
	"fmt"

	"github.com/spf13/pflag"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ContainerRuntimeOptions defines options for the container runtime.
type ContainerRuntimeOptions struct {
	// General Options.

	// ContainerRuntime is the container runtime to use.
	ContainerRuntime string
	// RuntimeCgroups that container runtime is expected to be isolated in.
	RuntimeCgroups string

	// Docker-specific options.

	// DockershimRootDirectory is the path to the dockershim root directory. Defaults to
	// /var/lib/dockershim if unset. Exposed for integration testing (e.g. in OpenShift).
	DockershimRootDirectory string
	// PodSandboxImage is the image whose network/ipc namespaces
	// containers in each pod will use.
	PodSandboxImage string
	// DockerEndpoint is the path to the docker endpoint to communicate with.
	DockerEndpoint string
	// If no pulling progress is made before the deadline imagePullProgressDeadline,
	// the image pulling will be cancelled. Defaults to 1m0s.
	// +optional
	ImagePullProgressDeadline metav1.Duration

	// Network plugin options.

	// networkPluginName is the name of the network plugin to be invoked for
	// various events in kubelet/pod lifecycle
	NetworkPluginName string
	// NetworkPluginMTU is the MTU to be passed to the network plugin,
	// and overrides the default MTU for cases where it cannot be automatically
	// computed (such as IPSEC).
	NetworkPluginMTU int32
	// CNIConfDir is the full path of the directory in which to search for
	// CNI config files
	CNIConfDir string
	// CNIBinDir is the full path of the directory in which to search for
	// CNI plugin binaries
	CNIBinDir string
	// CNICacheDir is the full path of the directory in which CNI should store
	// cache files
	CNICacheDir string

	// Image credential provider plugin options

	// ImageCredentialProviderConfigFile is the path to the credential provider plugin config file.
	// This config file is a specification for what credential providers are enabled and invokved
	// by the kubelet. The plugin config should contain information about what plugin binary
	// to execute and what container images the plugin should be called for.
	// +optional
	ImageCredentialProviderConfigFile string
	// ImageCredentialProviderBinDir is the path to the directory where credential provider plugin
	// binaries exist. The name of each plugin binary is expected to match the name of the plugin
	// specified in imageCredentialProviderConfigFile.
	// +optional
	ImageCredentialProviderBinDir string
}

// AddFlags adds flags to the container runtime, according to ContainerRuntimeOptions.
func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) {
	dockerOnlyWarning := "This docker-specific flag only works when container-runtime is set to docker."

	// General settings.
	fs.StringVar(&s.ContainerRuntime, "container-runtime", s.ContainerRuntime, "The container runtime to use. Possible values: 'docker', 'remote'.")
	fs.StringVar(&s.RuntimeCgroups, "runtime-cgroups", s.RuntimeCgroups, "Optional absolute name of cgroups to create and run the runtime in.")
	_ = fs.Bool("redirect-container-streaming", false, "[REMOVED]") // TODO: Delete in v1.22
	fs.MarkDeprecated("redirect-container-streaming", "Container streaming redirection has been removed from the kubelet as of v1.20, and this flag will be removed in v1.22. For more details, see https://git.k8s.io/enhancements/keps/sig-node/1558-streaming-proxy-redirects/README.md")

	// Docker-specific settings.
	fs.StringVar(&s.DockershimRootDirectory, "experimental-dockershim-root-directory", s.DockershimRootDirectory, "Path to the dockershim root directory.")
	fs.MarkHidden("experimental-dockershim-root-directory")
	fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, fmt.Sprintf("Specified image will not be pruned by the image garbage collector. "+
		"When container-runtime is set to 'docker', all containers in each pod will use the network/ipc namespaces from this image. Other CRI implementations have their own configuration to set this image."))
	fs.StringVar(&s.DockerEndpoint, "docker-endpoint", s.DockerEndpoint, fmt.Sprintf("Use this for the docker endpoint to communicate with. %s", dockerOnlyWarning))
	fs.MarkDeprecated("docker-endpoint", "will be removed along with dockershim.")
	fs.DurationVar(&s.ImagePullProgressDeadline.Duration, "image-pull-progress-deadline", s.ImagePullProgressDeadline.Duration, fmt.Sprintf("If no pulling progress is made before this deadline, the image pulling will be cancelled. %s", dockerOnlyWarning))
	fs.MarkDeprecated("image-pull-progress-deadline", "will be removed along with dockershim.")

	// Network plugin settings for Docker.
	fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, fmt.Sprintf("The name of the network plugin to be invoked for various events in kubelet/pod lifecycle. %s", dockerOnlyWarning))
	fs.MarkDeprecated("network-plugin", "will be removed along with dockershim.")
	fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, fmt.Sprintf("The full path of the directory in which to search for CNI config files. %s", dockerOnlyWarning))
	fs.MarkDeprecated("cni-conf-dir", "will be removed along with dockershim.")
	fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, fmt.Sprintf("A comma-separated list of full paths of directories in which to search for CNI plugin binaries. %s", dockerOnlyWarning))
	fs.MarkDeprecated("cni-bin-dir", "will be removed along with dockershim.")
	fs.StringVar(&s.CNICacheDir, "cni-cache-dir", s.CNICacheDir, fmt.Sprintf("The full path of the directory in which CNI should store cache files. %s", dockerOnlyWarning))
	fs.MarkDeprecated("cni-cache-dir", "will be removed along with dockershim.")
	fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, fmt.Sprintf("The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU. %s", dockerOnlyWarning))
	fs.MarkDeprecated("network-plugin-mtu", "will be removed along with dockershim.")

	// Image credential provider settings.
	fs.StringVar(&s.ImageCredentialProviderConfigFile, "image-credential-provider-config", s.ImageCredentialProviderConfigFile, "The path to the credential provider plugin config file.")
	fs.StringVar(&s.ImageCredentialProviderBinDir, "image-credential-provider-bin-dir", s.ImageCredentialProviderBinDir, "The path to the directory where credential provider plugin binaries are located.")
}
<|endoftext|>


<commit_before>/*
Copyright 2015 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 container

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

// OSInterface collects system level operations that need to be mocked out
// during tests.
type OSInterface interface {
	MkdirAll(path string, perm os.FileMode) error
	Symlink(oldname string, newname string) error
	Stat(path string) (os.FileInfo, error)
	Remove(path string) error
	RemoveAll(path string) error
	Create(path string) (*os.File, error)
	Chmod(path string, perm os.FileMode) error
	Hostname() (name string, err error)
	Chtimes(path string, atime time.Time, mtime time.Time) error
	Pipe() (r *os.File, w *os.File, err error)
	ReadDir(dirname string) ([]os.FileInfo, error)
	Glob(pattern string) ([]string, error)
}

// RealOS is used to dispatch the real system level operations.
type RealOS struct{}

// MkDir will will call os.Mkdir to create a directory.
func (RealOS) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(path, perm)
}

// Symlink will call os.Symlink to create a symbolic link.
func (RealOS) Symlink(oldname string, newname string) error {
	return os.Symlink(oldname, newname)
}

// Stat will call os.Stat to get the FileInfo for a given path
func (RealOS) Stat(path string) (os.FileInfo, error) {
	return os.Stat(path)
}

// Remove will call os.Remove to remove the path.
func (RealOS) Remove(path string) error {
	return os.Remove(path)
}

// RemoveAll will call os.RemoveAll to remove the path and its children.
func (RealOS) RemoveAll(path string) error {
	return os.RemoveAll(path)
}

// Create will call os.Create to create and return a file
// at path.
func (RealOS) Create(path string) (*os.File, error) {
	return os.Create(path)
}

// Chmod will change the permissions on the specified path or return
// an error.
func (RealOS) Chmod(path string, perm os.FileMode) error {
	return os.Chmod(path, perm)
}

// Hostname will call os.Hostname to return the hostname.
func (RealOS) Hostname() (name string, err error) {
	return os.Hostname()
}

// Chtimes will call os.Chtimes to change the atime and mtime of the path
func (RealOS) Chtimes(path string, atime time.Time, mtime time.Time) error {
	return os.Chtimes(path, atime, mtime)
}

// Pipe will call os.Pipe to return a connected pair of pipe.
func (RealOS) Pipe() (r *os.File, w *os.File, err error) {
	return os.Pipe()
}

// ReadDir will call ioutil.ReadDir to return the files under the directory.
func (RealOS) ReadDir(dirname string) ([]os.FileInfo, error) {
	return ioutil.ReadDir(dirname)
}

// Glob will call filepath.Glob to return the names of all files matching
// pattern.
func (RealOS) Glob(pattern string) ([]string, error) {
	return filepath.Glob(pattern)
}
<commit_msg>small nit in the annotations<commit_after>/*
Copyright 2015 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 container

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

// OSInterface collects system level operations that need to be mocked out
// during tests.
type OSInterface interface {
	MkdirAll(path string, perm os.FileMode) error
	Symlink(oldname string, newname string) error
	Stat(path string) (os.FileInfo, error)
	Remove(path string) error
	RemoveAll(path string) error
	Create(path string) (*os.File, error)
	Chmod(path string, perm os.FileMode) error
	Hostname() (name string, err error)
	Chtimes(path string, atime time.Time, mtime time.Time) error
	Pipe() (r *os.File, w *os.File, err error)
	ReadDir(dirname string) ([]os.FileInfo, error)
	Glob(pattern string) ([]string, error)
}

// RealOS is used to dispatch the real system level operations.
type RealOS struct{}

// MkdirAll will call os.MkdirAll to create a directory.
func (RealOS) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(path, perm)
}

// Symlink will call os.Symlink to create a symbolic link.
func (RealOS) Symlink(oldname string, newname string) error {
	return os.Symlink(oldname, newname)
}

// Stat will call os.Stat to get the FileInfo for a given path
func (RealOS) Stat(path string) (os.FileInfo, error) {
	return os.Stat(path)
}

// Remove will call os.Remove to remove the path.
func (RealOS) Remove(path string) error {
	return os.Remove(path)
}

// RemoveAll will call os.RemoveAll to remove the path and its children.
func (RealOS) RemoveAll(path string) error {
	return os.RemoveAll(path)
}

// Create will call os.Create to create and return a file
// at path.
func (RealOS) Create(path string) (*os.File, error) {
	return os.Create(path)
}

// Chmod will change the permissions on the specified path or return
// an error.
func (RealOS) Chmod(path string, perm os.FileMode) error {
	return os.Chmod(path, perm)
}

// Hostname will call os.Hostname to return the hostname.
func (RealOS) Hostname() (name string, err error) {
	return os.Hostname()
}

// Chtimes will call os.Chtimes to change the atime and mtime of the path
func (RealOS) Chtimes(path string, atime time.Time, mtime time.Time) error {
	return os.Chtimes(path, atime, mtime)
}

// Pipe will call os.Pipe to return a connected pair of pipe.
func (RealOS) Pipe() (r *os.File, w *os.File, err error) {
	return os.Pipe()
}

// ReadDir will call ioutil.ReadDir to return the files under the directory.
func (RealOS) ReadDir(dirname string) ([]os.FileInfo, error) {
	return ioutil.ReadDir(dirname)
}

// Glob will call filepath.Glob to return the names of all files matching
// pattern.
func (RealOS) Glob(pattern string) ([]string, error) {
	return filepath.Glob(pattern)
}
<|endoftext|>


<commit_before>package nginx

import (
	"github.com/jetstack/kube-lego/pkg/ingress"
	"github.com/jetstack/kube-lego/pkg/kubelego_const"
	"github.com/jetstack/kube-lego/pkg/service"

	"sort"

	"github.com/Sirupsen/logrus"
	k8sExtensions "k8s.io/client-go/pkg/apis/extensions/v1beta1"
)

var _ kubelego.IngressProvider = &Nginx{}

type Nginx struct {
	kubelego kubelego.KubeLego
	hosts    map[string]bool
	ingress  kubelego.Ingress
	service  kubelego.Service
}

func New(kl kubelego.KubeLego) *Nginx {
	return &Nginx{
		kubelego: kl,
		hosts:    map[string]bool{},
	}
}

func (p *Nginx) Log() (log *logrus.Entry) {
	return p.kubelego.Log().WithField("context", "provider").WithField("provider", "nginx")
}

func (p *Nginx) Reset() error {
	p.Log().Debug("reset")
	p.hosts = map[string]bool{}
	return nil
}

func (p *Nginx) Finalize() error {
	p.Log().Debug("finalize")

	if p.ingress == nil {
		p.ingress = ingress.New(p.kubelego, p.kubelego.LegoNamespace(), p.kubelego.LegoIngressNameNginx())
	}
	if p.service == nil {
		p.service = service.New(p.kubelego, p.kubelego.LegoNamespace(), p.kubelego.LegoServiceNameNginx())
	}

	if len(p.hosts) < 1 {
		p.Log().Info("disable provider no TLS hosts found")

		err := p.service.Delete()
		if err != nil {
			p.Log().Error(err)
		}

		err = p.ingress.Delete()
		if err != nil {
			p.Log().Error(err)
		}
	} else {
		err := p.updateService()
		if err != nil {
			p.Log().Error(err)
		}
		err = p.updateIngress()
		if err != nil {
			p.Log().Error(err)
		}
	}

	p.service = nil
	p.ingress = nil
	return nil
}

func (p *Nginx) getHosts() (hosts []string) {
	for host, enabled := range p.hosts {
		if enabled {
			hosts = append(hosts, host)
		}
	}
	sort.Strings(hosts)
	return
}

func (p *Nginx) updateService() error {

	p.service.SetKubeLegoSpec()
	return p.service.Save()

}

func (p *Nginx) updateIngress() error {

	ing := p.ingress.Object()
	rules := []k8sExtensions.IngressRule{}
	paths := []k8sExtensions.HTTPIngressPath{
		k8sExtensions.HTTPIngressPath{
			Path: kubelego.AcmeHttpChallengePath,
			Backend: k8sExtensions.IngressBackend{
				ServiceName: p.kubelego.LegoServiceNameNginx(),
				ServicePort: p.kubelego.LegoHTTPPort(),
			},
		},
	}
	ruleValue := k8sExtensions.IngressRuleValue{
		&k8sExtensions.HTTPIngressRuleValue{
			Paths: paths,
		},
	}
	for _, host := range p.getHosts() {
		rules = append(rules, k8sExtensions.IngressRule{
			Host:             host,
			IngressRuleValue: ruleValue,
		})
	}

	ing.Annotations = map[string]string{
		kubelego.AnnotationIngressChallengeEndpoints: "true",
		kubelego.AnnotationSslRedirect:               "false",
		// TODO: use the ingres class as specified on the ingress we are
		// requesting a certificate for
		kubelego.AnnotationIngressClass:         p.kubelego.LegoDefaultIngressClass(),
		kubelego.AnnotationIngressProvider:      "nginx",
		kubelego.AnnotationWhitelistSourceRange: "0.0.0.0/0",
	}

	ing.Spec = k8sExtensions.IngressSpec{
		Rules: rules,
	}

	return p.ingress.Save()
}

func (p *Nginx) Process(ing kubelego.Ingress) error {
	for _, tls := range ing.Tls() {
		for _, host := range tls.Hosts() {
			p.hosts[host] = true
		}
	}
	return nil
}
<commit_msg>Whitelist IPv6 default route<commit_after>package nginx

import (
	"github.com/jetstack/kube-lego/pkg/ingress"
	"github.com/jetstack/kube-lego/pkg/kubelego_const"
	"github.com/jetstack/kube-lego/pkg/service"

	"sort"

	"github.com/Sirupsen/logrus"
	k8sExtensions "k8s.io/client-go/pkg/apis/extensions/v1beta1"
)

var _ kubelego.IngressProvider = &Nginx{}

type Nginx struct {
	kubelego kubelego.KubeLego
	hosts    map[string]bool
	ingress  kubelego.Ingress
	service  kubelego.Service
}

func New(kl kubelego.KubeLego) *Nginx {
	return &Nginx{
		kubelego: kl,
		hosts:    map[string]bool{},
	}
}

func (p *Nginx) Log() (log *logrus.Entry) {
	return p.kubelego.Log().WithField("context", "provider").WithField("provider", "nginx")
}

func (p *Nginx) Reset() error {
	p.Log().Debug("reset")
	p.hosts = map[string]bool{}
	return nil
}

func (p *Nginx) Finalize() error {
	p.Log().Debug("finalize")

	if p.ingress == nil {
		p.ingress = ingress.New(p.kubelego, p.kubelego.LegoNamespace(), p.kubelego.LegoIngressNameNginx())
	}
	if p.service == nil {
		p.service = service.New(p.kubelego, p.kubelego.LegoNamespace(), p.kubelego.LegoServiceNameNginx())
	}

	if len(p.hosts) < 1 {
		p.Log().Info("disable provider no TLS hosts found")

		err := p.service.Delete()
		if err != nil {
			p.Log().Error(err)
		}

		err = p.ingress.Delete()
		if err != nil {
			p.Log().Error(err)
		}
	} else {
		err := p.updateService()
		if err != nil {
			p.Log().Error(err)
		}
		err = p.updateIngress()
		if err != nil {
			p.Log().Error(err)
		}
	}

	p.service = nil
	p.ingress = nil
	return nil
}

func (p *Nginx) getHosts() (hosts []string) {
	for host, enabled := range p.hosts {
		if enabled {
			hosts = append(hosts, host)
		}
	}
	sort.Strings(hosts)
	return
}

func (p *Nginx) updateService() error {

	p.service.SetKubeLegoSpec()
	return p.service.Save()

}

func (p *Nginx) updateIngress() error {

	ing := p.ingress.Object()
	rules := []k8sExtensions.IngressRule{}
	paths := []k8sExtensions.HTTPIngressPath{
		k8sExtensions.HTTPIngressPath{
			Path: kubelego.AcmeHttpChallengePath,
			Backend: k8sExtensions.IngressBackend{
				ServiceName: p.kubelego.LegoServiceNameNginx(),
				ServicePort: p.kubelego.LegoHTTPPort(),
			},
		},
	}
	ruleValue := k8sExtensions.IngressRuleValue{
		&k8sExtensions.HTTPIngressRuleValue{
			Paths: paths,
		},
	}
	for _, host := range p.getHosts() {
		rules = append(rules, k8sExtensions.IngressRule{
			Host:             host,
			IngressRuleValue: ruleValue,
		})
	}

	ing.Annotations = map[string]string{
		kubelego.AnnotationIngressChallengeEndpoints: "true",
		kubelego.AnnotationSslRedirect:               "false",
		// TODO: use the ingres class as specified on the ingress we are
		// requesting a certificate for
		kubelego.AnnotationIngressClass:         p.kubelego.LegoDefaultIngressClass(),
		kubelego.AnnotationIngressProvider:      "nginx",
		kubelego.AnnotationWhitelistSourceRange: "0.0.0.0/0,::/0",
	}

	ing.Spec = k8sExtensions.IngressSpec{
		Rules: rules,
	}

	return p.ingress.Save()
}

func (p *Nginx) Process(ing kubelego.Ingress) error {
	for _, tls := range ing.Tls() {
		for _, host := range tls.Hosts() {
			p.hosts[host] = true
		}
	}
	return 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 minion

import (
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strconv"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors"
)

// nodeStrategy implements behavior for nodes
type nodeStrategy struct {
	runtime.ObjectTyper
	api.NameGenerator
}

// Nodes is the default logic that applies when creating and updating Node
// objects.
var Strategy = nodeStrategy{api.Scheme, api.SimpleNameGenerator}

// NamespaceScoped is false for nodes.
func (nodeStrategy) NamespaceScoped() bool {
	return false
}

// AllowCreateOnUpdate is false for nodes.
func (nodeStrategy) AllowCreateOnUpdate() bool {
	return false
}

// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
func (nodeStrategy) PrepareForCreate(obj runtime.Object) {
	_ = obj.(*api.Node)
	// Nodes allow *all* fields, including status, to be set on create.
}

// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
func (nodeStrategy) PrepareForUpdate(obj, old runtime.Object) {
	newNode := obj.(*api.Node)
	oldNode := old.(*api.Node)
	newNode.Status = oldNode.Status
}

// Validate validates a new node.
func (nodeStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList {
	node := obj.(*api.Node)
	return validation.ValidateNode(node)
}

// ValidateUpdate is the default update validation for an end user.
func (nodeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
	errorList := validation.ValidateNode(obj.(*api.Node))
	return append(errorList, validation.ValidateNodeUpdate(old.(*api.Node), obj.(*api.Node))...)
}

type nodeStatusStrategy struct {
	nodeStrategy
}

var StatusStrategy = nodeStatusStrategy{Strategy}

func (nodeStatusStrategy) PrepareForCreate(obj runtime.Object) {
	_ = obj.(*api.Node)
	// Nodes allow *all* fields, including status, to be set on create.
}

func (nodeStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
	newNode := obj.(*api.Node)
	oldNode := old.(*api.Node)
	newNode.Spec = oldNode.Spec
}

func (nodeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
	return validation.ValidateNodeUpdate(old.(*api.Node), obj.(*api.Node))
}

// ResourceGetter is an interface for retrieving resources by ResourceLocation.
type ResourceGetter interface {
	Get(api.Context, string) (runtime.Object, error)
}

// NodeToSelectableFields returns a label set that represents the object.
func NodeToSelectableFields(node *api.Node) fields.Set {
	return fields.Set{
		"metadata.name":      node.Name,
		"spec.unschedulable": fmt.Sprint(node.Spec.Unschedulable),
	}
}

// MatchNode returns a generic matcher for a given label and field selector.
func MatchNode(label labels.Selector, field fields.Selector) generic.Matcher {
	return &generic.SelectionPredicate{
		Label: label,
		Field: field,
		GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
			nodeObj, ok := obj.(*api.Node)
			if !ok {
				return nil, nil, fmt.Errorf("not a node")
			}
			return labels.Set(nodeObj.ObjectMeta.Labels), NodeToSelectableFields(nodeObj), nil
		},
	}
}

// ResourceLocation returns a URL to which one can send traffic for the specified node.
func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGetter, ctx api.Context, id string) (*url.URL, http.RoundTripper, error) {
	name, portReq, valid := util.SplitPort(id)
	if !valid {
		return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid node request %q", id))
	}

	nodeObj, err := getter.Get(ctx, name)
	if err != nil {
		return nil, nil, err
	}
	node := nodeObj.(*api.Node)
	host := node.Name // TODO: use node's IP, don't expect the name to resolve.

	if portReq != "" {
		return &url.URL{Host: net.JoinHostPort(host, portReq)}, nil, nil
	}

	scheme, port, transport, err := connection.GetConnectionInfo(host)
	if err != nil {
		return nil, nil, err
	}

	return &url.URL{
			Scheme: scheme,
			Host: net.JoinHostPort(
				host,
				strconv.FormatUint(uint64(port), 10),
			),
		},
		transport,
		nil
}
<commit_msg>Nodes returns transport and scheme in spite of port requirements<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 minion

import (
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strconv"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors"
)

// nodeStrategy implements behavior for nodes
type nodeStrategy struct {
	runtime.ObjectTyper
	api.NameGenerator
}

// Nodes is the default logic that applies when creating and updating Node
// objects.
var Strategy = nodeStrategy{api.Scheme, api.SimpleNameGenerator}

// NamespaceScoped is false for nodes.
func (nodeStrategy) NamespaceScoped() bool {
	return false
}

// AllowCreateOnUpdate is false for nodes.
func (nodeStrategy) AllowCreateOnUpdate() bool {
	return false
}

// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
func (nodeStrategy) PrepareForCreate(obj runtime.Object) {
	_ = obj.(*api.Node)
	// Nodes allow *all* fields, including status, to be set on create.
}

// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
func (nodeStrategy) PrepareForUpdate(obj, old runtime.Object) {
	newNode := obj.(*api.Node)
	oldNode := old.(*api.Node)
	newNode.Status = oldNode.Status
}

// Validate validates a new node.
func (nodeStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList {
	node := obj.(*api.Node)
	return validation.ValidateNode(node)
}

// ValidateUpdate is the default update validation for an end user.
func (nodeStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
	errorList := validation.ValidateNode(obj.(*api.Node))
	return append(errorList, validation.ValidateNodeUpdate(old.(*api.Node), obj.(*api.Node))...)
}

type nodeStatusStrategy struct {
	nodeStrategy
}

var StatusStrategy = nodeStatusStrategy{Strategy}

func (nodeStatusStrategy) PrepareForCreate(obj runtime.Object) {
	_ = obj.(*api.Node)
	// Nodes allow *all* fields, including status, to be set on create.
}

func (nodeStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
	newNode := obj.(*api.Node)
	oldNode := old.(*api.Node)
	newNode.Spec = oldNode.Spec
}

func (nodeStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
	return validation.ValidateNodeUpdate(old.(*api.Node), obj.(*api.Node))
}

// ResourceGetter is an interface for retrieving resources by ResourceLocation.
type ResourceGetter interface {
	Get(api.Context, string) (runtime.Object, error)
}

// NodeToSelectableFields returns a label set that represents the object.
func NodeToSelectableFields(node *api.Node) fields.Set {
	return fields.Set{
		"metadata.name":      node.Name,
		"spec.unschedulable": fmt.Sprint(node.Spec.Unschedulable),
	}
}

// MatchNode returns a generic matcher for a given label and field selector.
func MatchNode(label labels.Selector, field fields.Selector) generic.Matcher {
	return &generic.SelectionPredicate{
		Label: label,
		Field: field,
		GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
			nodeObj, ok := obj.(*api.Node)
			if !ok {
				return nil, nil, fmt.Errorf("not a node")
			}
			return labels.Set(nodeObj.ObjectMeta.Labels), NodeToSelectableFields(nodeObj), nil
		},
	}
}

// ResourceLocation returns an URL and transport which one can use to send traffic for the specified node.
func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGetter, ctx api.Context, id string) (*url.URL, http.RoundTripper, error) {
	name, portReq, valid := util.SplitPort(id)
	if !valid {
		return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid node request %q", id))
	}

	nodeObj, err := getter.Get(ctx, name)
	if err != nil {
		return nil, nil, err
	}
	node := nodeObj.(*api.Node)
	host := node.Name // TODO: use node's IP, don't expect the name to resolve.

	scheme, port, transport, err := connection.GetConnectionInfo(host)
	if err != nil {
		return nil, nil, err
	}

	if portReq != "" {
		return &url.URL{Scheme: scheme, Host: net.JoinHostPort(host, portReq)}, transport, nil
	}

	return &url.URL{
			Scheme: scheme,
			Host: net.JoinHostPort(
				host,
				strconv.FormatUint(uint64(port), 10),
			),
		},
		transport,
		nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 webhook implements a generic HTTP webhook plugin.
package webhook

import (
	"context"
	"fmt"
	"time"

	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apimachinery/pkg/util/net"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

// defaultRequestTimeout is set for all webhook request. This is the absolute
// timeout of the HTTP request, including reading the response body.
const defaultRequestTimeout = 30 * time.Second

// GenericWebhook defines a generic client for webhooks with commonly used capabilities,
// such as retry requests.
type GenericWebhook struct {
	RestClient     *rest.RESTClient
	InitialBackoff time.Duration
	ShouldRetry    func(error) bool
}

// DefaultShouldRetry is a default implementation for the GenericWebhook ShouldRetry function property.
// If the error reason is one of: networking (connection reset) or http (InternalServerError (500), GatewayTimeout (504), TooManyRequests (429)),
// or apierrors.SuggestsClientDelay() returns true, then the function advises a retry.
// Otherwise it returns false for an immediate fail.
func DefaultShouldRetry(err error) bool {
	// these errors indicate a transient error that should be retried.
	if net.IsConnectionReset(err) || apierrors.IsInternalError(err) || apierrors.IsTimeout(err) || apierrors.IsTooManyRequests(err) {
		return true
	}
	// if the error sends the Retry-After header, we respect it as an explicit confirmation we should retry.
	if _, shouldRetry := apierrors.SuggestsClientDelay(err); shouldRetry {
		return true
	}
	return false
}

// NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file.
func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
	return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout, customDial)
}

func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
	for _, groupVersion := range groupVersions {
		if !scheme.IsVersionRegistered(groupVersion) {
			return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion)
		}
	}

	loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
	loadingRules.ExplicitPath = kubeConfigFile
	loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

	clientConfig, err := loader.ClientConfig()
	if err != nil {
		return nil, err
	}

	// Kubeconfigs can't set a timeout, this can only be set through a command line flag.
	//
	// https://github.com/kubernetes/client-go/blob/master/tools/clientcmd/overrides.go
	//
	// Set this to something reasonable so request to webhooks don't hang forever.
	clientConfig.Timeout = requestTimeout

	// Avoid client-side rate limiting talking to the webhook backend.
	// Rate limiting should happen when deciding how many requests to serve.
	clientConfig.QPS = -1

	codec := codecFactory.LegacyCodec(groupVersions...)
	clientConfig.ContentConfig.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})

	clientConfig.Dial = customDial

	restClient, err := rest.UnversionedRESTClientFor(clientConfig)
	if err != nil {
		return nil, err
	}

	return &GenericWebhook{restClient, initialBackoff, DefaultShouldRetry}, nil
}

// WithExponentialBackoff will retry webhookFn() up to 5 times with exponentially increasing backoff when
// it returns an error for which this GenericWebhook's ShouldRetry function returns true, confirming it to
// be retriable. If no ShouldRetry has been defined for the webhook, then the default one is used (DefaultShouldRetry).
func (g *GenericWebhook) WithExponentialBackoff(ctx context.Context, webhookFn func() rest.Result) rest.Result {
	var result rest.Result
	shouldRetry := g.ShouldRetry
	if shouldRetry == nil {
		shouldRetry = DefaultShouldRetry
	}
	WithExponentialBackoff(ctx, g.InitialBackoff, func() error {
		result = webhookFn()
		return result.Error()
	}, shouldRetry)
	return result
}

// WithExponentialBackoff will retry webhookFn up to 5 times with exponentially increasing backoff when
// it returns an error for which shouldRetry returns true, confirming it to be retriable.
func WithExponentialBackoff(ctx context.Context, initialBackoff time.Duration, webhookFn func() error, shouldRetry func(error) bool) error {
	backoff := wait.Backoff{
		Duration: initialBackoff,
		Factor:   1.5,
		Jitter:   0.2,
		Steps:    5,
	}

	var err error
	wait.ExponentialBackoff(backoff, func() (bool, error) {
		err = webhookFn()
		if ctx.Err() != nil {
			// we timed out or were cancelled, we should not retry
			return true, err
		}
		if shouldRetry(err) {
			return false, nil
		}
		if err != nil {
			return false, err
		}
		return true, nil
	})
	return err
}
<commit_msg>Remove double import of k8s.io/apimachinery/pkg/util/net<commit_after>/*
Copyright 2016 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 webhook implements a generic HTTP webhook plugin.
package webhook

import (
	"context"
	"fmt"
	"time"

	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

// defaultRequestTimeout is set for all webhook request. This is the absolute
// timeout of the HTTP request, including reading the response body.
const defaultRequestTimeout = 30 * time.Second

// GenericWebhook defines a generic client for webhooks with commonly used capabilities,
// such as retry requests.
type GenericWebhook struct {
	RestClient     *rest.RESTClient
	InitialBackoff time.Duration
	ShouldRetry    func(error) bool
}

// DefaultShouldRetry is a default implementation for the GenericWebhook ShouldRetry function property.
// If the error reason is one of: networking (connection reset) or http (InternalServerError (500), GatewayTimeout (504), TooManyRequests (429)),
// or apierrors.SuggestsClientDelay() returns true, then the function advises a retry.
// Otherwise it returns false for an immediate fail.
func DefaultShouldRetry(err error) bool {
	// these errors indicate a transient error that should be retried.
	if utilnet.IsConnectionReset(err) || apierrors.IsInternalError(err) || apierrors.IsTimeout(err) || apierrors.IsTooManyRequests(err) {
		return true
	}
	// if the error sends the Retry-After header, we respect it as an explicit confirmation we should retry.
	if _, shouldRetry := apierrors.SuggestsClientDelay(err); shouldRetry {
		return true
	}
	return false
}

// NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file.
func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
	return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout, customDial)
}

func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
	for _, groupVersion := range groupVersions {
		if !scheme.IsVersionRegistered(groupVersion) {
			return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion)
		}
	}

	loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
	loadingRules.ExplicitPath = kubeConfigFile
	loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})

	clientConfig, err := loader.ClientConfig()
	if err != nil {
		return nil, err
	}

	// Kubeconfigs can't set a timeout, this can only be set through a command line flag.
	//
	// https://github.com/kubernetes/client-go/blob/master/tools/clientcmd/overrides.go
	//
	// Set this to something reasonable so request to webhooks don't hang forever.
	clientConfig.Timeout = requestTimeout

	// Avoid client-side rate limiting talking to the webhook backend.
	// Rate limiting should happen when deciding how many requests to serve.
	clientConfig.QPS = -1

	codec := codecFactory.LegacyCodec(groupVersions...)
	clientConfig.ContentConfig.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})

	clientConfig.Dial = customDial

	restClient, err := rest.UnversionedRESTClientFor(clientConfig)
	if err != nil {
		return nil, err
	}

	return &GenericWebhook{restClient, initialBackoff, DefaultShouldRetry}, nil
}

// WithExponentialBackoff will retry webhookFn() up to 5 times with exponentially increasing backoff when
// it returns an error for which this GenericWebhook's ShouldRetry function returns true, confirming it to
// be retriable. If no ShouldRetry has been defined for the webhook, then the default one is used (DefaultShouldRetry).
func (g *GenericWebhook) WithExponentialBackoff(ctx context.Context, webhookFn func() rest.Result) rest.Result {
	var result rest.Result
	shouldRetry := g.ShouldRetry
	if shouldRetry == nil {
		shouldRetry = DefaultShouldRetry
	}
	WithExponentialBackoff(ctx, g.InitialBackoff, func() error {
		result = webhookFn()
		return result.Error()
	}, shouldRetry)
	return result
}

// WithExponentialBackoff will retry webhookFn up to 5 times with exponentially increasing backoff when
// it returns an error for which shouldRetry returns true, confirming it to be retriable.
func WithExponentialBackoff(ctx context.Context, initialBackoff time.Duration, webhookFn func() error, shouldRetry func(error) bool) error {
	backoff := wait.Backoff{
		Duration: initialBackoff,
		Factor:   1.5,
		Jitter:   0.2,
		Steps:    5,
	}

	var err error
	wait.ExponentialBackoff(backoff, func() (bool, error) {
		err = webhookFn()
		if ctx.Err() != nil {
			// we timed out or were cancelled, we should not retry
			return true, err
		}
		if shouldRetry(err) {
			return false, nil
		}
		if err != nil {
			return false, err
		}
		return true, nil
	})
	return err
}
<|endoftext|>


<commit_before>package solr

import "testing"
import "fmt"

func TestConnection(t *testing.T) {
	fmt.Println("Running TestConnection")
	/*body,_ := HTTPGet("http://igeonote.com/api/geoip/country/66.249.66.20")

	res,_ := bytes2Json(&body)
	fmt.Println(fmt.Sprintf("%s", *res))
	*/
}

func TestBytes2Json(t *testing.T) {
	data := []byte(`{"t":"s","two":2,"obj":{"c":"b","j":"F"},"a":[1,2,3]}`)
	d, _ := bytes2json(&data)
	if d["t"] != "s" {
		t.Errorf("t should have s as value")
	}

	if d["two"].(float64) != 2 {
		t.Errorf("two should have 2 as value")
	}

	PrintMapInterface(d)
}

func PrintMapInterface(d map[string]interface{}) {
	for k, v := range d {
		switch vv := v.(type) {
		case string:
			fmt.Println(fmt.Sprintf("%s:%s", k, v))
		case int:
			fmt.Println(k, "is int", vv)
		case float64:
			fmt.Println(k, "is float", vv)
		case map[string]interface{}:
			fmt.Println(k, "type is map[string]interface{}")
			for i, u := range vv {
				fmt.Println(i, u)
			}
		case []interface{}:
			fmt.Println(k, "type is []interface{}")
			for i, u := range vv {
				fmt.Println(i, u)
			}
		default:
			fmt.Println(k, "is of a type I don't know how to handle", vv)
		}
	}
}

func TestJson2Bytes(t *testing.T) {

	test_json := map[string]interface{}{
		"t":   "s",
		"two": 2,
		"obj": map[string]interface{}{"c": "b", "j": "F"},
		"a":   []interface{}{1, 2, 3},
	}

	b, err := json2bytes(test_json)
	if err != nil {
		fmt.Println(err)
	}
	d, _ := bytes2json(b)

	if d["t"] != "s" {
		t.Errorf("t should have s as value")
	}

	if d["two"].(float64) != 2 {
		t.Errorf("two should have 2 as value")
	}

	PrintMapInterface(d)
}

func TestHasError(t *testing.T) {
	data := map[string]interface{}{
		"responseHeader": map[string]interface{}{
			"status": 400,
			"QTime":  30,
			"params": map[string]interface{}{
				"indent": "true",
				"q":      "**",
				"wt":     "json"}},
		"error": map[string]interface{}{
			"msg":  "no field name specified in query and no default specified via 'df' param",
			"code": 400}}

	if hasError(data) != true {
		t.Errorf("Should have an error")
	}

	data2 := map[string]interface{}{
		"responseHeader": map[string]interface{}{
			"status": 400,
			"QTime":  30,
			"params": map[string]interface{}{
				"indent": "true",
				"q":      "**",
				"wt":     "json"}},
		"response": map[string]interface{}{
			"numFound": 1,
			"start":    0,
			"docs": []map[string]interface{}{{
				"id":        "change.me",
				"title":     "change.me",
				"_version_": 14}}}}

	if hasError(data2) != false {
		t.Errorf("Should not has an error")
	}
}
<commit_msg>Printing recursive on map[string]interface{}<commit_after>package solr

import "testing"
import "fmt"

func TestConnection(t *testing.T) {
	fmt.Println("Running TestConnection")
	/*body,_ := HTTPGet("http://igeonote.com/api/geoip/country/66.249.66.20")

	res,_ := bytes2Json(&body)
	fmt.Println(fmt.Sprintf("%s", *res))
	*/
}

func TestBytes2Json(t *testing.T) {
	data := []byte(`{"t":"s","two":2,"obj":{"c":"b","j":"F"},"a":[1,2,3]}`)
	d, _ := bytes2json(&data)
	if d["t"] != "s" {
		t.Errorf("t should have s as value")
	}

	if d["two"].(float64) != 2 {
		t.Errorf("two should have 2 as value")
	}

	PrintMapInterface(d)
}

func PrintMapInterface(d map[string]interface{}) {
	for k, v := range d {
		switch vv := v.(type) {
		case string:
			fmt.Println(fmt.Sprintf("%s:%s", k, v))
		case int:
			fmt.Println(k, "is int", vv)
		case float64:
			fmt.Println(k, "is float", vv)
		case map[string]interface{}:
			fmt.Println(k, "type is map[string]interface{}")
			PrintMapInterface(vv)
		case []interface{}:
			fmt.Println(k, "type is []interface{}")
			for i, u := range vv {
				switch uu := u.(type) {
				case map[string]interface{}:
					PrintMapInterface(uu)
				default:
					fmt.Println(i, u)
				}
			}
		default:
			fmt.Println(k, "is of a type I don't know how to handle", vv)
		}
	}
}

func TestJson2Bytes(t *testing.T) {

	test_json := map[string]interface{}{
		"t":   "s",
		"two": 2,
		"obj": map[string]interface{}{"c": "b", "j": "F"},
		"a":   []interface{}{1, 2, 3},
	}

	b, err := json2bytes(test_json)
	if err != nil {
		fmt.Println(err)
	}
	d, _ := bytes2json(b)

	if d["t"] != "s" {
		t.Errorf("t should have s as value")
	}

	if d["two"].(float64) != 2 {
		t.Errorf("two should have 2 as value")
	}

	PrintMapInterface(d)
}

func TestHasError(t *testing.T) {
	data := map[string]interface{}{
		"responseHeader": map[string]interface{}{
			"status": 400,
			"QTime":  30,
			"params": map[string]interface{}{
				"indent": "true",
				"q":      "**",
				"wt":     "json"}},
		"error": map[string]interface{}{
			"msg":  "no field name specified in query and no default specified via 'df' param",
			"code": 400}}

	if hasError(data) != true {
		t.Errorf("Should have an error")
	}

	data2 := map[string]interface{}{
		"responseHeader": map[string]interface{}{
			"status": 400,
			"QTime":  30,
			"params": map[string]interface{}{
				"indent": "true",
				"q":      "**",
				"wt":     "json"}},
		"response": map[string]interface{}{
			"numFound": 1,
			"start":    0,
			"docs": []map[string]interface{}{{
				"id":        "change.me",
				"title":     "change.me",
				"_version_": 14}}}}

	if hasError(data2) != false {
		t.Errorf("Should not has an error")
	}
}
<|endoftext|>


<commit_before>package http

import (
	"net"
	"net/http"
)

type consumer struct {
	conn  net.Conn
	close chan bool
}

func newConsumer(resp http.ResponseWriter) (*consumer, error) {
	conn, _, err := resp.(http.Hijacker).Hijack()
	if err != nil {
		return nil, err
	}
	conn.Write([]byte("HTTP/1.1 200 OK\nContent-Type: text/event-stream\nX-Accel-Buffering: no\n\n"))

	return &consumer{conn, make(chan bool)}, nil
}
<commit_msg>Set write deadline to zero<commit_after>package http

import (
	"net"
	"net/http"
	"time"
)

type consumer struct {
	conn  net.Conn
	close chan bool
}

func newConsumer(resp http.ResponseWriter) (*consumer, error) {
	conn, _, err := resp.(http.Hijacker).Hijack()
	if err != nil {
		return nil, err
	}

	conn.SetWriteDeadline(time.Time{})
	conn.Write([]byte("HTTP/1.1 200 OK\nContent-Type: text/event-stream\nX-Accel-Buffering: no\n\n"))

	return &consumer{conn, make(chan bool)}, nil
}
<|endoftext|>


<commit_before>package somatree

import (
	"fmt"
	"log"
	"reflect"

	"github.com/satori/go.uuid"
)

type SomaTreeElemFault struct {
	Id     uuid.UUID
	Name   string
	Type   string
	State  string
	Parent SomaTreeFaultReceiver `json:"-"`
	Errors []error
}

//
// NEW
func NewFault() *SomaTreeElemFault {
	tef := new(SomaTreeElemFault)
	tef.Id = uuid.NewV4()
	tef.Type = "fault"
	tef.Name = "McFaulty"
	tef.Errors = make([]error, 0)
	tef.State = "floating"

	return tef
}

//
// Interface: SomaTreeBuilder
func (tef *SomaTreeElemFault) GetID() string {
	return tef.Id.String()
}

func (tef *SomaTreeElemFault) GetName() string {
	return tef.Name
}

func (tef *SomaTreeElemFault) GetType() string {
	return tef.Type
}

func (tef SomaTreeElemFault) CloneRepository() SomaTreeRepositoryAttacher {
	return &tef
}

//
// Interface: SomaTreeAttacher
func (tef *SomaTreeElemFault) Attach(a AttachRequest) {
	switch {
	case a.ParentType == "repository":
		tef.attachToRepository(a)
	}
}

func (tef *SomaTreeElemFault) ReAttach(a AttachRequest) {
	log.Fatal("Not implemented")
}

func (tef *SomaTreeElemFault) setParent(p SomaTreeReceiver) {
	switch p.(type) {
	case SomaTreeFaultReceiver:
		tef.setFaultParent(p.(SomaTreeFaultReceiver))
		tef.State = "attached"
	default:
		fmt.Printf("Type: %s\n", reflect.TypeOf(p))
		panic(`SomaTreeElemFault.setParent`)
	}
}

func (tef *SomaTreeElemFault) setFaultParent(p SomaTreeFaultReceiver) {
	tef.Parent = p
}

func (tef *SomaTreeElemFault) clearParent() {
	tef.Parent = nil
	tef.State = "floating"
}

func (tef *SomaTreeElemFault) Destroy() {
	if tef.Parent == nil {
		panic(`SomaTreeElemFault.Destroy called without Parent to unlink from`)
	}

	tef.Parent.Unlink(UnlinkRequest{
		ParentType: tef.Parent.(SomaTreeBuilder).GetType(),
		ParentId:   tef.Parent.(SomaTreeBuilder).GetID(),
		ParentName: tef.Parent.(SomaTreeBuilder).GetName(),
		ChildType:  tef.GetType(),
		ChildName:  tef.GetName(),
		ChildId:    tef.GetID(),
	},
	)
}

func (tef *SomaTreeElemFault) Detach() {
	tef.Destroy()
}

//
// Interface: SomaTreeRepositoryAttacher
func (tef *SomaTreeElemFault) attachToRepository(a AttachRequest) {
	a.Root.Receive(ReceiveRequest{
		ParentType: a.ParentType,
		ParentId:   a.ParentId,
		ParentName: a.ParentName,
		ChildType:  tef.Type,
		Fault:      tef,
	})
}

//
// Interface: SomaTreeReceiver
func (tef *SomaTreeElemFault) Receive(r ReceiveRequest) {
}

//
// Interface: SomaTreeBucketeer
func (tef *SomaTreeElemFault) GetBucket() SomaTreeReceiver {
	return tef
}

//
// Interface: SomaTreeUnlinker
func (tef *SomaTreeElemFault) Unlink(u UnlinkRequest) {
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>SomaTreeElemFault: cleanup implemented interfaces<commit_after>package somatree

import (
	"fmt"
	"log"
	"reflect"

	"github.com/satori/go.uuid"
)

type SomaTreeElemFault struct {
	Id     uuid.UUID
	Name   string
	Type   string
	State  string
	Parent SomaTreeFaultReceiver `json:"-"`
	Errors []error
}

//
// NEW
func NewFault() *SomaTreeElemFault {
	tef := new(SomaTreeElemFault)
	tef.Id = uuid.NewV4()
	tef.Type = "fault"
	tef.Name = "McFaulty"
	tef.Errors = make([]error, 0)
	tef.State = "floating"

	return tef
}

//
// Interface: SomaTreeBuilder
func (tef *SomaTreeElemFault) GetID() string {
	return tef.Id.String()
}

func (tef *SomaTreeElemFault) GetName() string {
	return tef.Name
}

func (tef *SomaTreeElemFault) GetType() string {
	return tef.Type
}

func (tef SomaTreeElemFault) CloneRepository() SomaTreeRepositoryAttacher {
	return &tef
}

//
// Interface: SomaTreeAttacher
func (tef *SomaTreeElemFault) Attach(a AttachRequest) {
	switch {
	case a.ParentType == "repository":
		tef.attachToRepository(a)
	}
}

func (tef *SomaTreeElemFault) ReAttach(a AttachRequest) {
	log.Fatal("Not implemented")
}

func (tef *SomaTreeElemFault) setParent(p SomaTreeReceiver) {
	switch p.(type) {
	case SomaTreeFaultReceiver:
		tef.setFaultParent(p.(SomaTreeFaultReceiver))
		tef.State = "attached"
	default:
		fmt.Printf("Type: %s\n", reflect.TypeOf(p))
		panic(`SomaTreeElemFault.setParent`)
	}
}

func (tef *SomaTreeElemFault) setFaultParent(p SomaTreeFaultReceiver) {
	tef.Parent = p
}

func (tef *SomaTreeElemFault) clearParent() {
	tef.Parent = nil
	tef.State = "floating"
}

func (tef *SomaTreeElemFault) Destroy() {
	if tef.Parent == nil {
		panic(`SomaTreeElemFault.Destroy called without Parent to unlink from`)
	}

	tef.Parent.Unlink(UnlinkRequest{
		ParentType: tef.Parent.(SomaTreeBuilder).GetType(),
		ParentId:   tef.Parent.(SomaTreeBuilder).GetID(),
		ParentName: tef.Parent.(SomaTreeBuilder).GetName(),
		ChildType:  tef.GetType(),
		ChildName:  tef.GetName(),
		ChildId:    tef.GetID(),
	},
	)
}

func (tef *SomaTreeElemFault) Detach() {
	tef.Destroy()
}

//
// Interface: SomaTreeRepositoryAttacher
func (tef *SomaTreeElemFault) attachToRepository(a AttachRequest) {
	a.Root.Receive(ReceiveRequest{
		ParentType: a.ParentType,
		ParentId:   a.ParentId,
		ParentName: a.ParentName,
		ChildType:  tef.Type,
		Fault:      tef,
	})
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>package goczmq

import (
	"bufio"
	"fmt"
	"os"
	"path"
	"testing"
)

func TestAuthIPAllow(t *testing.T) {
	auth := NewAuth()
	defer auth.Destroy()

	var err error

	if testing.Verbose() {
		err = auth.Verbose()
		if err != nil {
			t.Error(err)
		}
	}

	err = auth.Allow("127.0.0.1")
	if err != nil {
		t.Error(err)
	}

	server := NewSock(Pull)
	server.SetZapDomain("global")
	defer server.Destroy()

	port, err := server.Bind("tcp://127.0.0.1:*")
	if err != nil {
		t.Error(err)
	}

	client := NewSock(Push)
	defer client.Destroy()

	err = client.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	client.SendFrame([]byte("Hello"), 1)
	client.SendFrame([]byte("World"), 0)

	poller, err := NewPoller(server)
	if err != nil {
		t.Error(err)
	}
	defer poller.Destroy()

	s := poller.Wait(200)
	if want, have := server, s; want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	msg, err := s.RecvMessage()
	if err != nil {
		t.Error(err)
	}

	if want, have := "Hello", string(msg[0]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	if want, have := "World", string(msg[1]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}
}

func TestAuthPlain(t *testing.T) {
	pwfile, err := os.Create("./password_test.txt")
	if err != nil {
		t.Error(err)
	}

	defer func() {
		os.Remove("./password_test.txt")
	}()

	w := bufio.NewWriter(pwfile)
	w.Write([]byte("admin=Password\n"))
	w.Flush()
	pwfile.Close()

	auth := NewAuth()
	defer auth.Destroy()

	if testing.Verbose() {
		err = auth.Verbose()
		if err != nil {
			t.Error(err)
		}
	}

	err = auth.Allow("127.0.0.1")
	if err != nil {
		t.Error(err)
	}

	err = auth.Plain("./password_test.txt")
	if err != nil {
		t.Error(err)
	}

	server := NewSock(Pull)
	defer server.Destroy()
	server.SetZapDomain("global")
	server.SetPlainServer(1)

	port, err := server.Bind("tcp://127.0.0.1:*")
	if err != nil {
		t.Error(err)
	}

	goodClient := NewSock(Push)
	defer goodClient.Destroy()
	goodClient.SetPlainUsername("admin")
	goodClient.SetPlainPassword("Password")

	badClient := NewSock(Push)
	defer badClient.Destroy()
	badClient.SetPlainUsername("admin")
	badClient.SetPlainPassword("BadPassword")

	err = goodClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	goodClient.SendFrame([]byte("Hello"), 1)
	goodClient.SendFrame([]byte("World"), 0)

	poller, err := NewPoller(server)
	if err != nil {
		t.Error(err)
	}
	defer poller.Destroy()

	s := poller.Wait(200)
	if want, have := server, s; want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	msg, err := s.RecvMessage()
	if err != nil {
		t.Error(err)
	}

	if want, have := "Hello", string(msg[0]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	if want, have := "World", string(msg[1]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	err = badClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	badClient.SendFrame([]byte("Hello"), 1)
	badClient.SendFrame([]byte("World"), 0)

	s = poller.Wait(200)
	if s != nil {
		t.Errorf("want %#v, have %#v", nil, s)
	}

	if want, have := "Hello", string(msg[0]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	if want, have := "World", string(msg[1]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}
}

func TestAuthCurveAllowAny(t *testing.T) {
	auth := NewAuth()
	defer auth.Destroy()

	var err error

	if testing.Verbose() {
		err = auth.Verbose()
		if err != nil {
			t.Error(err)
		}
	}

	server := NewSock(Pull)
	defer server.Destroy()
	server.SetZapDomain("global")
	serverCert := NewCert()
	serverKey := serverCert.PublicText()
	serverCert.Apply(server)
	server.SetCurveServer(1)

	goodClient := NewSock(Push)
	defer goodClient.Destroy()
	goodClientCert := NewCert()
	goodClientCert.Apply(goodClient)
	goodClient.SetCurveServerkey(serverKey)

	badClient := NewSock(Push)
	defer badClient.Destroy()

	auth.Curve(CurveAllowAny)

	port, err := server.Bind("tcp://127.0.0.1:*")
	if err != nil {
		t.Error(err)
	}

	err = goodClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	err = badClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	goodClient.SendFrame([]byte("Hello"), 1)
	goodClient.SendFrame([]byte("World"), 0)

	poller, err := NewPoller(server)
	if err != nil {
		t.Error(err)
	}
	defer poller.Destroy()

	s := poller.Wait(2000)
	if want, have := server, s; want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	msg, err := s.RecvMessage()
	if err != nil {
		t.Error(err)
	}

	if want, have := "Hello", string(msg[0]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	if want, have := "World", string(msg[1]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	badClient.SendFrame([]byte("Hello"), 1)
	badClient.SendFrame([]byte("Bad World"), 0)

	s = poller.Wait(200)
	if s != nil {
		t.Errorf("want %#v, have %#v", nil, s)
	}
}

func TestAuthCurveAllowCertificate(t *testing.T) {
	testpath := path.Join("testauth")
	err := os.Mkdir(testpath, 0777)
	if err != nil {
		t.Error(err)
	}

	auth := NewAuth()
	defer auth.Destroy()

	if testing.Verbose() {
		err = auth.Verbose()
		if err != nil {
			t.Error(err)
		}
	}

	server := NewSock(Pull)
	defer server.Destroy()
	server.SetZapDomain("global")
	serverCert := NewCert()
	serverKey := serverCert.PublicText()
	serverCert.Apply(server)
	server.SetCurveServer(1)

	goodClient := NewSock(Push)
	defer goodClient.Destroy()
	goodClientCert := NewCert()
	defer goodClientCert.Destroy()
	goodClientCert.Apply(goodClient)
	goodClient.SetCurveServerkey(serverKey)

	certfile := path.Join("testauth", "goodClient.txt")
	goodClientCert.SavePublic(certfile)

	badClient := NewSock(Push)
	defer badClient.Destroy()
	badClientCert := NewCert()
	defer badClientCert.Destroy()
	badClientCert.Apply(badClient)
	badClient.SetCurveServerkey(serverKey)

	err = auth.Curve(testpath)
	if err != nil {
		t.Error(err)
	}

	port, err := server.Bind("tcp://127.0.0.1:*")
	if err != nil {
		t.Error(err)
	}

	err = goodClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	err = badClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	goodClient.SendFrame([]byte("Hello, Good World!"), 0)

	poller, err := NewPoller(server)
	if err != nil {
		t.Error(err)
	}
	defer poller.Destroy()

	s := poller.Wait(200)
	if want, have := server, s; want != have {
		t.Errorf("want '%#v', have '%#v'", want, have)
	}

	msg, err := s.RecvMessage()
	if err != nil {
		t.Error(err)
	}

	if want, have := "Hello, Good World!", string(msg[0]); want != have {
		t.Errorf("want '%#v', have '%#v'", want, have)
	}

	badClient.SendFrame([]byte("Hello, Bad World"), 0)

	s = poller.Wait(200)
	if s != nil {
		t.Errorf("want '%#v', have '%#v", nil, s)
	}

	os.RemoveAll(testpath)
}

func ExampleAuth() {
	// create a server certificate
	serverCert := NewCert()
	defer serverCert.Destroy()

	// create a client certificate and save it
	clientCert := NewCert()
	defer clientCert.Destroy()
	clientCert.SavePublic("client_cert")
	defer func() { os.Remove("client_cert") }()

	// create an auth service
	auth := NewAuth()
	defer auth.Destroy()

	// tell the auth service the client cert is allowed
	auth.Curve("client_cert")

	// create a server socket and set it to
	// use the "global" auth domain
	server := NewSock(Push)
	defer server.Destroy()
	server.SetZapDomain("global")

	// set the server cert as the server cert
	// for the socket we created and set it
	// to be a curve server
	serverCert.Apply(server)
	server.SetCurveServer(1)

	// bind our server to an endpoint
	server.Bind("inproc://auth_example")

	// create a client socket
	client := NewSock(Pull)
	defer client.Destroy()

	// assign the client cert we made to the client
	clientCert.Apply(client)

	// set the server cert as the server cert
	// for the client. for the client to be
	// allowed to connect, it needs to know
	// the servers public cert.
	client.SetCurveServerkey(serverCert.PublicText())

	// connect
	client.Connect("inproc://auth_example")
}
<commit_msg>Problem: auth example used inproc<commit_after>package goczmq

import (
	"bufio"
	"fmt"
	"os"
	"path"
	"testing"
)

func TestAuthIPAllow(t *testing.T) {
	auth := NewAuth()
	defer auth.Destroy()

	var err error

	if testing.Verbose() {
		err = auth.Verbose()
		if err != nil {
			t.Error(err)
		}
	}

	err = auth.Allow("127.0.0.1")
	if err != nil {
		t.Error(err)
	}

	server := NewSock(Pull)
	server.SetZapDomain("global")
	defer server.Destroy()

	port, err := server.Bind("tcp://127.0.0.1:*")
	if err != nil {
		t.Error(err)
	}

	client := NewSock(Push)
	defer client.Destroy()

	err = client.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	client.SendFrame([]byte("Hello"), 1)
	client.SendFrame([]byte("World"), 0)

	poller, err := NewPoller(server)
	if err != nil {
		t.Error(err)
	}
	defer poller.Destroy()

	s := poller.Wait(200)
	if want, have := server, s; want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	msg, err := s.RecvMessage()
	if err != nil {
		t.Error(err)
	}

	if want, have := "Hello", string(msg[0]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	if want, have := "World", string(msg[1]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}
}

func TestAuthPlain(t *testing.T) {
	pwfile, err := os.Create("./password_test.txt")
	if err != nil {
		t.Error(err)
	}

	defer func() {
		os.Remove("./password_test.txt")
	}()

	w := bufio.NewWriter(pwfile)
	w.Write([]byte("admin=Password\n"))
	w.Flush()
	pwfile.Close()

	auth := NewAuth()
	defer auth.Destroy()

	if testing.Verbose() {
		err = auth.Verbose()
		if err != nil {
			t.Error(err)
		}
	}

	err = auth.Allow("127.0.0.1")
	if err != nil {
		t.Error(err)
	}

	err = auth.Plain("./password_test.txt")
	if err != nil {
		t.Error(err)
	}

	server := NewSock(Pull)
	defer server.Destroy()
	server.SetZapDomain("global")
	server.SetPlainServer(1)

	port, err := server.Bind("tcp://127.0.0.1:*")
	if err != nil {
		t.Error(err)
	}

	goodClient := NewSock(Push)
	defer goodClient.Destroy()
	goodClient.SetPlainUsername("admin")
	goodClient.SetPlainPassword("Password")

	badClient := NewSock(Push)
	defer badClient.Destroy()
	badClient.SetPlainUsername("admin")
	badClient.SetPlainPassword("BadPassword")

	err = goodClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	goodClient.SendFrame([]byte("Hello"), 1)
	goodClient.SendFrame([]byte("World"), 0)

	poller, err := NewPoller(server)
	if err != nil {
		t.Error(err)
	}
	defer poller.Destroy()

	s := poller.Wait(200)
	if want, have := server, s; want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	msg, err := s.RecvMessage()
	if err != nil {
		t.Error(err)
	}

	if want, have := "Hello", string(msg[0]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	if want, have := "World", string(msg[1]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	err = badClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	badClient.SendFrame([]byte("Hello"), 1)
	badClient.SendFrame([]byte("World"), 0)

	s = poller.Wait(200)
	if s != nil {
		t.Errorf("want %#v, have %#v", nil, s)
	}

	if want, have := "Hello", string(msg[0]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	if want, have := "World", string(msg[1]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}
}

func TestAuthCurveAllowAny(t *testing.T) {
	auth := NewAuth()
	defer auth.Destroy()

	var err error

	if testing.Verbose() {
		err = auth.Verbose()
		if err != nil {
			t.Error(err)
		}
	}

	server := NewSock(Pull)
	defer server.Destroy()
	server.SetZapDomain("global")
	serverCert := NewCert()
	serverKey := serverCert.PublicText()
	serverCert.Apply(server)
	server.SetCurveServer(1)

	goodClient := NewSock(Push)
	defer goodClient.Destroy()
	goodClientCert := NewCert()
	goodClientCert.Apply(goodClient)
	goodClient.SetCurveServerkey(serverKey)

	badClient := NewSock(Push)
	defer badClient.Destroy()

	auth.Curve(CurveAllowAny)

	port, err := server.Bind("tcp://127.0.0.1:*")
	if err != nil {
		t.Error(err)
	}

	err = goodClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	err = badClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	goodClient.SendFrame([]byte("Hello"), 1)
	goodClient.SendFrame([]byte("World"), 0)

	poller, err := NewPoller(server)
	if err != nil {
		t.Error(err)
	}
	defer poller.Destroy()

	s := poller.Wait(2000)
	if want, have := server, s; want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	msg, err := s.RecvMessage()
	if err != nil {
		t.Error(err)
	}

	if want, have := "Hello", string(msg[0]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	if want, have := "World", string(msg[1]); want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	badClient.SendFrame([]byte("Hello"), 1)
	badClient.SendFrame([]byte("Bad World"), 0)

	s = poller.Wait(200)
	if s != nil {
		t.Errorf("want %#v, have %#v", nil, s)
	}
}

func TestAuthCurveAllowCertificate(t *testing.T) {
	testpath := path.Join("testauth")
	err := os.Mkdir(testpath, 0777)
	if err != nil {
		t.Error(err)
	}

	auth := NewAuth()
	defer auth.Destroy()

	if testing.Verbose() {
		err = auth.Verbose()
		if err != nil {
			t.Error(err)
		}
	}

	server := NewSock(Pull)
	defer server.Destroy()
	server.SetZapDomain("global")
	serverCert := NewCert()
	serverKey := serverCert.PublicText()
	serverCert.Apply(server)
	server.SetCurveServer(1)

	goodClient := NewSock(Push)
	defer goodClient.Destroy()
	goodClientCert := NewCert()
	defer goodClientCert.Destroy()
	goodClientCert.Apply(goodClient)
	goodClient.SetCurveServerkey(serverKey)

	certfile := path.Join("testauth", "goodClient.txt")
	goodClientCert.SavePublic(certfile)

	badClient := NewSock(Push)
	defer badClient.Destroy()
	badClientCert := NewCert()
	defer badClientCert.Destroy()
	badClientCert.Apply(badClient)
	badClient.SetCurveServerkey(serverKey)

	err = auth.Curve(testpath)
	if err != nil {
		t.Error(err)
	}

	port, err := server.Bind("tcp://127.0.0.1:*")
	if err != nil {
		t.Error(err)
	}

	err = goodClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	err = badClient.Connect(fmt.Sprintf("tcp://127.0.0.1:%d", port))
	if err != nil {
		t.Error(err)
	}

	goodClient.SendFrame([]byte("Hello, Good World!"), 0)

	poller, err := NewPoller(server)
	if err != nil {
		t.Error(err)
	}
	defer poller.Destroy()

	s := poller.Wait(200)
	if want, have := server, s; want != have {
		t.Errorf("want '%#v', have '%#v'", want, have)
	}

	msg, err := s.RecvMessage()
	if err != nil {
		t.Error(err)
	}

	if want, have := "Hello, Good World!", string(msg[0]); want != have {
		t.Errorf("want '%#v', have '%#v'", want, have)
	}

	badClient.SendFrame([]byte("Hello, Bad World"), 0)

	s = poller.Wait(200)
	if s != nil {
		t.Errorf("want '%#v', have '%#v", nil, s)
	}

	os.RemoveAll(testpath)
}

func ExampleAuth() {
	// create a server certificate
	serverCert := NewCert()
	defer serverCert.Destroy()

	// create a client certificate and save it
	clientCert := NewCert()
	defer clientCert.Destroy()
	clientCert.SavePublic("client_cert")
	defer func() { os.Remove("client_cert") }()

	// create an auth service
	auth := NewAuth()
	defer auth.Destroy()

	// tell the auth service the client cert is allowed
	auth.Curve("client_cert")

	// create a server socket and set it to
	// use the "global" auth domain
	server := NewSock(Push)
	defer server.Destroy()
	server.SetZapDomain("global")

	// set the server cert as the server cert
	// for the socket we created and set it
	// to be a curve server
	serverCert.Apply(server)
	server.SetCurveServer(1)

	// bind our server to an endpoint
	server.Bind("tcp://*:9898")

	// create a client socket
	client := NewSock(Pull)
	defer client.Destroy()

	// assign the client cert we made to the client
	clientCert.Apply(client)

	// set the server cert as the server cert
	// for the client. for the client to be
	// allowed to connect, it needs to know
	// the servers public cert.
	client.SetCurveServerkey(serverCert.PublicText())

	// connect
	client.Connect("tcp://127.0.0.1:9898")
}
<|endoftext|>