<commit_before>package e2e

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

	appsv1 "k8s.io/api/apps/v1"
	v1 "k8s.io/api/core/v1"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"k8s.io/kubernetes/pkg/client/conditions"
	"k8s.io/kubernetes/test/e2e/framework"
	e2elog "k8s.io/kubernetes/test/e2e/framework/log"
)

// getDaemonSetLabelSelector returns labels of daemonset given name and namespace dynamically,
// needed since labels are not same for helm and non-helm deployments.
func getDaemonSetLabelSelector(f *framework.Framework, ns, daemonSetName string) (string, error) {
	ds, err := f.ClientSet.AppsV1().DaemonSets(ns).Get(context.TODO(), daemonSetName, metav1.GetOptions{})
	if err != nil {
		e2elog.Logf("Error getting daemonsets with name %s in namespace %s", daemonSetName, ns)
		return "", err
	}
	s, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector)
	if err != nil {
		e2elog.Logf("Error parsing %s daemonset selector in namespace %s", daemonSetName, ns)
		return "", err
	}
	e2elog.Logf("LabelSelector for %s daemonsets in namespace %s: %s", daemonSetName, ns, s.String())
	return s.String(), nil
}

func waitForDaemonSets(name, ns string, c kubernetes.Interface, t int) error {
	timeout := time.Duration(t) * time.Minute
	start := time.Now()
	e2elog.Logf("Waiting up to %v for all daemonsets in namespace '%s' to start", timeout, ns)

	return wait.PollImmediate(poll, timeout, func() (bool, error) {
		ds, err := c.AppsV1().DaemonSets(ns).Get(context.TODO(), name, metav1.GetOptions{})
		if err != nil {
			e2elog.Logf("Error getting daemonsets in namespace: '%s': %v", ns, err)
			if strings.Contains(err.Error(), "not found") {
				return false, nil
			}
			if isRetryableAPIError(err) {
				return false, nil
			}
			return false, err
		}
		dNum := ds.Status.DesiredNumberScheduled
		ready := ds.Status.NumberReady
		e2elog.Logf(
			"%d / %d pods ready in namespace '%s' in daemonset '%s' (%d seconds elapsed)",
			ready,
			dNum,
			ns,
			ds.ObjectMeta.Name,
			int(time.Since(start).Seconds()))
		if ready != dNum {
			return false, nil
		}

		return true, nil
	})
}

// Waits for the deployment to complete.

func waitForDeploymentComplete(name, ns string, c kubernetes.Interface, t int) error {
	var (
		deployment *appsv1.Deployment
		reason     string
		err        error
	)
	timeout := time.Duration(t) * time.Minute
	err = wait.PollImmediate(poll, timeout, func() (bool, error) {
		deployment, err = c.AppsV1().Deployments(ns).Get(context.TODO(), name, metav1.GetOptions{})
		if err != nil {
			if isRetryableAPIError(err) {
				return false, nil
			}
			e2elog.Logf("deployment error: %v", err)
			return false, err
		}

		// TODO need to check rolling update

		// When the deployment status and its underlying resources reach the
		// desired state, we're done
		if deployment.Status.Replicas == deployment.Status.ReadyReplicas {
			return true, nil
		}
		e2elog.Logf(
			"deployment status: expected replica count %d running replica count %d",
			deployment.Status.Replicas,
			deployment.Status.ReadyReplicas)
		reason = fmt.Sprintf("deployment status: %#v", deployment.Status.String())
		return false, nil
	})

	if errors.Is(err, wait.ErrWaitTimeout) {
		err = fmt.Errorf("%s", reason)
	}
	if err != nil {
		return fmt.Errorf("error waiting for deployment %q status to match expectation: %w", name, err)
	}
	return nil
}

func findPodAndContainerName(f *framework.Framework, ns, cn string, opt *metav1.ListOptions) (string, string, error) {
	podList, err := f.PodClientNS(ns).List(context.TODO(), *opt)
	if err != nil {
		return "", "", err
	}

	if len(podList.Items) == 0 {
		return "", "", errors.New("podlist is empty")
	}

	if cn != "" {
		for i := range podList.Items {
			for j := range podList.Items[i].Spec.Containers {
				if podList.Items[i].Spec.Containers[j].Name == cn {
					return podList.Items[i].Name, cn, nil
				}
			}
		}
		return "", "", errors.New("container name not found")
	}
	return podList.Items[0].Name, podList.Items[0].Spec.Containers[0].Name, nil
}

func getCommandInPodOpts(
	f *framework.Framework,
	c, ns, cn string,
	opt *metav1.ListOptions) (framework.ExecOptions, error) {
	cmd := []string{"/bin/sh", "-c", c}
	pName, cName, err := findPodAndContainerName(f, ns, cn, opt)
	if err != nil {
		return framework.ExecOptions{}, err
	}
	return framework.ExecOptions{
		Command:            cmd,
		PodName:            pName,
		Namespace:          ns,
		ContainerName:      cName,
		Stdin:              nil,
		CaptureStdout:      true,
		CaptureStderr:      true,
		PreserveWhitespace: true,
	}, nil
}

// execCommandInDaemonsetPod executes commands inside given container of a daemonset pod on a particular node.
func execCommandInDaemonsetPod(
	f *framework.Framework,
	c, daemonsetName, nodeName, containerName, ns string) (string, string, error) {
	selector, err := getDaemonSetLabelSelector(f, ns, daemonsetName)
	if err != nil {
		return "", "", err
	}

	opt := &metav1.ListOptions{
		LabelSelector: selector,
	}
	pods, err := listPods(f, ns, opt)
	if err != nil {
		return "", "", err
	}

	podName := ""
	for i := range pods {
		if pods[i].Spec.NodeName == nodeName {
			podName = pods[i].Name
		}
	}
	if podName == "" {
		return "", "", fmt.Errorf("%s daemonset pod on node %s in namespace %s not found", daemonsetName, nodeName, ns)
	}

	cmd := []string{"/bin/sh", "-c", c}
	podOpt := framework.ExecOptions{
		Command:       cmd,
		Namespace:     ns,
		PodName:       podName,
		ContainerName: containerName,
		CaptureStdout: true,
		CaptureStderr: true,
	}
	return f.ExecWithOptions(podOpt)
}

// listPods returns slice of pods matching given ListOptions and namespace.
func listPods(f *framework.Framework, ns string, opt *metav1.ListOptions) ([]v1.Pod, error) {
	podList, err := f.PodClientNS(ns).List(context.TODO(), *opt)
	if len(podList.Items) == 0 {
		return podList.Items, fmt.Errorf("podlist for label '%s' in namespace %s is empty", opt.LabelSelector, ns)
	}
	return podList.Items, err
}

func execCommandInPod(f *framework.Framework, c, ns string, opt *metav1.ListOptions) (string, string, error) {
	podOpt, err := getCommandInPodOpts(f, c, ns, "", opt)
	if err != nil {
		return "", "", err
	}
	stdOut, stdErr, err := f.ExecWithOptions(podOpt)
	if stdErr != "" {
		e2elog.Logf("stdErr occurred: %v", stdErr)
	}
	return stdOut, stdErr, err
}

//nolint:unparam // cn can be used with different inputs later
func execCommandInContainer(
	f *framework.Framework, c, ns, cn string, opt *metav1.ListOptions) (string, string, error) {
	podOpt, err := getCommandInPodOpts(f, c, ns, cn, opt)
	if err != nil {
		return "", "", err
	}
	stdOut, stdErr, err := f.ExecWithOptions(podOpt)
	if stdErr != "" {
		e2elog.Logf("stdErr occurred: %v", stdErr)
	}
	return stdOut, stdErr, err
}

func execCommandInToolBoxPod(f *framework.Framework, c, ns string) (string, string, error) {
	opt := &metav1.ListOptions{
		LabelSelector: rookToolBoxPodLabel,
	}
	podOpt, err := getCommandInPodOpts(f, c, ns, "", opt)
	if err != nil {
		return "", "", err
	}
	stdOut, stdErr, err := f.ExecWithOptions(podOpt)
	if stdErr != "" {
		e2elog.Logf("stdErr occurred: %v", stdErr)
	}
	return stdOut, stdErr, err
}

func execCommandInPodAndAllowFail(f *framework.Framework, c, ns string, opt *metav1.ListOptions) (string, string) {
	podOpt, err := getCommandInPodOpts(f, c, ns, "", opt)
	if err != nil {
		return "", err.Error()
	}
	stdOut, stdErr, err := f.ExecWithOptions(podOpt)
	if err != nil {
		e2elog.Logf("command %s failed: %v", c, err)
	}
	return stdOut, stdErr
}

func loadApp(path string) (*v1.Pod, error) {
	app := v1.Pod{}
	if err := unmarshal(path, &app); err != nil {
		return nil, err
	}
	for i := range app.Spec.Containers {
		app.Spec.Containers[i].ImagePullPolicy = v1.PullIfNotPresent
	}
	return &app, nil
}

func createApp(c kubernetes.Interface, app *v1.Pod, timeout int) error {
	_, err := c.CoreV1().Pods(app.Namespace).Create(context.TODO(), app, metav1.CreateOptions{})
	if err != nil {
		return fmt.Errorf("failed to create app: %w", err)
	}
	return waitForPodInRunningState(app.Name, app.Namespace, c, timeout, noError)
}

func createAppErr(c kubernetes.Interface, app *v1.Pod, timeout int, errString string) error {
	_, err := c.CoreV1().Pods(app.Namespace).Create(context.TODO(), app, metav1.CreateOptions{})
	if err != nil {
		return err
	}
	return waitForPodInRunningState(app.Name, app.Namespace, c, timeout, errString)
}

func waitForPodInRunningState(name, ns string, c kubernetes.Interface, t int, expectedError string) error {
	timeout := time.Duration(t) * time.Minute
	start := time.Now()
	e2elog.Logf("Waiting up to %v to be in Running state", name)
	return wait.PollImmediate(poll, timeout, func() (bool, error) {
		pod, err := c.CoreV1().Pods(ns).Get(context.TODO(), name, metav1.GetOptions{})
		if err != nil {
			if isRetryableAPIError(err) {
				return false, nil
			}
			return false, fmt.Errorf("failed to get app: %w", err)
		}
		switch pod.Status.Phase {
		case v1.PodRunning:
			return true, nil
		case v1.PodFailed, v1.PodSucceeded:
			return false, conditions.ErrPodCompleted
		case v1.PodPending:
			if expectedError != "" {
				events, err := c.CoreV1().Events(ns).List(context.TODO(), metav1.ListOptions{
					FieldSelector: fmt.Sprintf("involvedObject.name=%s", name),
				})
				if err != nil {
					return false, err
				}
				if strings.Contains(events.String(), expectedError) {
					e2elog.Logf("Expected Error %q found successfully", expectedError)
					return true, err
				}
			}
		case v1.PodUnknown:
			e2elog.Logf(
				"%s app  is in %s phase expected to be in Running  state (%d seconds elapsed)",
				name,
				pod.Status.Phase,
				int(time.Since(start).Seconds()))
		}
		return false, nil
	})
}

func deletePod(name, ns string, c kubernetes.Interface, t int) error {
	timeout := time.Duration(t) * time.Minute
	err := c.CoreV1().Pods(ns).Delete(context.TODO(), name, metav1.DeleteOptions{})
	if err != nil {
		return fmt.Errorf("failed to delete app: %w", err)
	}
	start := time.Now()
	e2elog.Logf("Waiting for pod %v to be deleted", name)
	return wait.PollImmediate(poll, timeout, func() (bool, error) {
		_, err := c.CoreV1().Pods(ns).Get(context.TODO(), name, metav1.GetOptions{})
		if err != nil {
			if isRetryableAPIError(err) {
				return false, nil
			}
			if apierrs.IsNotFound(err) {
				return true, nil
			}
			e2elog.Logf("%s app  to be deleted (%d seconds elapsed)", name, int(time.Since(start).Seconds()))
			return false, fmt.Errorf("failed to get app: %w", err)
		}
		return false, nil
	})
}

//nolint:unparam // skipNotFound arg can be used with different inputs later
func deletePodWithLabel(label, ns string, skipNotFound bool) error {
	_, err := framework.RunKubectl(ns, "delete", "po", "-l", label, fmt.Sprintf("--ignore-not-found=%t", skipNotFound))
	if err != nil {
		e2elog.Logf("failed to delete pod %v", err)
	}
	return err
}

// calculateSHA512sum returns the sha512sum of a file inside a pod.
func calculateSHA512sum(f *framework.Framework, app *v1.Pod, filePath string, opt *metav1.ListOptions) (string, error) {
	cmd := fmt.Sprintf("sha512sum %s", filePath)
	sha512sumOut, stdErr, err := execCommandInPod(f, cmd, app.Namespace, opt)
	if err != nil {
		return "", err
	}
	if stdErr != "" {
		return "", fmt.Errorf("error: sha512sum could not be calculated %v", stdErr)
	}
	// extract checksum from sha512sum output.
	checkSum := strings.Split(sha512sumOut, "")[0]
	e2elog.Logf("Calculated checksum  %s", checkSum)
	return checkSum, nil
}
<commit_msg>ci: fix nolintlint warnings<commit_after>package e2e

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

	appsv1 "k8s.io/api/apps/v1"
	v1 "k8s.io/api/core/v1"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"k8s.io/kubernetes/pkg/client/conditions"
	"k8s.io/kubernetes/test/e2e/framework"
	e2elog "k8s.io/kubernetes/test/e2e/framework/log"
)

// getDaemonSetLabelSelector returns labels of daemonset given name and namespace dynamically,
// needed since labels are not same for helm and non-helm deployments.
func getDaemonSetLabelSelector(f *framework.Framework, ns, daemonSetName string) (string, error) {
	ds, err := f.ClientSet.AppsV1().DaemonSets(ns).Get(context.TODO(), daemonSetName, metav1.GetOptions{})
	if err != nil {
		e2elog.Logf("Error getting daemonsets with name %s in namespace %s", daemonSetName, ns)
		return "", err
	}
	s, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector)
	if err != nil {
		e2elog.Logf("Error parsing %s daemonset selector in namespace %s", daemonSetName, ns)
		return "", err
	}
	e2elog.Logf("LabelSelector for %s daemonsets in namespace %s: %s", daemonSetName, ns, s.String())
	return s.String(), nil
}

func waitForDaemonSets(name, ns string, c kubernetes.Interface, t int) error {
	timeout := time.Duration(t) * time.Minute
	start := time.Now()
	e2elog.Logf("Waiting up to %v for all daemonsets in namespace '%s' to start", timeout, ns)

	return wait.PollImmediate(poll, timeout, func() (bool, error) {
		ds, err := c.AppsV1().DaemonSets(ns).Get(context.TODO(), name, metav1.GetOptions{})
		if err != nil {
			e2elog.Logf("Error getting daemonsets in namespace: '%s': %v", ns, err)
			if strings.Contains(err.Error(), "not found") {
				return false, nil
			}
			if isRetryableAPIError(err) {
				return false, nil
			}
			return false, err
		}
		dNum := ds.Status.DesiredNumberScheduled
		ready := ds.Status.NumberReady
		e2elog.Logf(
			"%d / %d pods ready in namespace '%s' in daemonset '%s' (%d seconds elapsed)",
			ready,
			dNum,
			ns,
			ds.ObjectMeta.Name,
			int(time.Since(start).Seconds()))
		if ready != dNum {
			return false, nil
		}

		return true, nil
	})
}

// Waits for the deployment to complete.

func waitForDeploymentComplete(name, ns string, c kubernetes.Interface, t int) error {
	var (
		deployment *appsv1.Deployment
		reason     string
		err        error
	)
	timeout := time.Duration(t) * time.Minute
	err = wait.PollImmediate(poll, timeout, func() (bool, error) {
		deployment, err = c.AppsV1().Deployments(ns).Get(context.TODO(), name, metav1.GetOptions{})
		if err != nil {
			if isRetryableAPIError(err) {
				return false, nil
			}
			e2elog.Logf("deployment error: %v", err)
			return false, err
		}

		// TODO need to check rolling update

		// When the deployment status and its underlying resources reach the
		// desired state, we're done
		if deployment.Status.Replicas == deployment.Status.ReadyReplicas {
			return true, nil
		}
		e2elog.Logf(
			"deployment status: expected replica count %d running replica count %d",
			deployment.Status.Replicas,
			deployment.Status.ReadyReplicas)
		reason = fmt.Sprintf("deployment status: %#v", deployment.Status.String())
		return false, nil
	})

	if errors.Is(err, wait.ErrWaitTimeout) {
		err = fmt.Errorf("%s", reason)
	}
	if err != nil {
		return fmt.Errorf("error waiting for deployment %q status to match expectation: %w", name, err)
	}
	return nil
}

func findPodAndContainerName(f *framework.Framework, ns, cn string, opt *metav1.ListOptions) (string, string, error) {
	podList, err := f.PodClientNS(ns).List(context.TODO(), *opt)
	if err != nil {
		return "", "", err
	}

	if len(podList.Items) == 0 {
		return "", "", errors.New("podlist is empty")
	}

	if cn != "" {
		for i := range podList.Items {
			for j := range podList.Items[i].Spec.Containers {
				if podList.Items[i].Spec.Containers[j].Name == cn {
					return podList.Items[i].Name, cn, nil
				}
			}
		}
		return "", "", errors.New("container name not found")
	}
	return podList.Items[0].Name, podList.Items[0].Spec.Containers[0].Name, nil
}

func getCommandInPodOpts(
	f *framework.Framework,
	c, ns, cn string,
	opt *metav1.ListOptions) (framework.ExecOptions, error) {
	cmd := []string{"/bin/sh", "-c", c}
	pName, cName, err := findPodAndContainerName(f, ns, cn, opt)
	if err != nil {
		return framework.ExecOptions{}, err
	}
	return framework.ExecOptions{
		Command:            cmd,
		PodName:            pName,
		Namespace:          ns,
		ContainerName:      cName,
		Stdin:              nil,
		CaptureStdout:      true,
		CaptureStderr:      true,
		PreserveWhitespace: true,
	}, nil
}

// execCommandInDaemonsetPod executes commands inside given container of a daemonset pod on a particular node.
func execCommandInDaemonsetPod(
	f *framework.Framework,
	c, daemonsetName, nodeName, containerName, ns string) (string, string, error) {
	selector, err := getDaemonSetLabelSelector(f, ns, daemonsetName)
	if err != nil {
		return "", "", err
	}

	opt := &metav1.ListOptions{
		LabelSelector: selector,
	}
	pods, err := listPods(f, ns, opt)
	if err != nil {
		return "", "", err
	}

	podName := ""
	for i := range pods {
		if pods[i].Spec.NodeName == nodeName {
			podName = pods[i].Name
		}
	}
	if podName == "" {
		return "", "", fmt.Errorf("%s daemonset pod on node %s in namespace %s not found", daemonsetName, nodeName, ns)
	}

	cmd := []string{"/bin/sh", "-c", c}
	podOpt := framework.ExecOptions{
		Command:       cmd,
		Namespace:     ns,
		PodName:       podName,
		ContainerName: containerName,
		CaptureStdout: true,
		CaptureStderr: true,
	}
	return f.ExecWithOptions(podOpt)
}

// listPods returns slice of pods matching given ListOptions and namespace.
func listPods(f *framework.Framework, ns string, opt *metav1.ListOptions) ([]v1.Pod, error) {
	podList, err := f.PodClientNS(ns).List(context.TODO(), *opt)
	if len(podList.Items) == 0 {
		return podList.Items, fmt.Errorf("podlist for label '%s' in namespace %s is empty", opt.LabelSelector, ns)
	}
	return podList.Items, err
}

func execCommandInPod(f *framework.Framework, c, ns string, opt *metav1.ListOptions) (string, string, error) {
	podOpt, err := getCommandInPodOpts(f, c, ns, "", opt)
	if err != nil {
		return "", "", err
	}
	stdOut, stdErr, err := f.ExecWithOptions(podOpt)
	if stdErr != "" {
		e2elog.Logf("stdErr occurred: %v", stdErr)
	}
	return stdOut, stdErr, err
}

func execCommandInContainer(
	f *framework.Framework, c, ns, cn string, opt *metav1.ListOptions) (string, string, error) {
	podOpt, err := getCommandInPodOpts(f, c, ns, cn, opt)
	if err != nil {
		return "", "", err
	}
	stdOut, stdErr, err := f.ExecWithOptions(podOpt)
	if stdErr != "" {
		e2elog.Logf("stdErr occurred: %v", stdErr)
	}
	return stdOut, stdErr, err
}

func execCommandInToolBoxPod(f *framework.Framework, c, ns string) (string, string, error) {
	opt := &metav1.ListOptions{
		LabelSelector: rookToolBoxPodLabel,
	}
	podOpt, err := getCommandInPodOpts(f, c, ns, "", opt)
	if err != nil {
		return "", "", err
	}
	stdOut, stdErr, err := f.ExecWithOptions(podOpt)
	if stdErr != "" {
		e2elog.Logf("stdErr occurred: %v", stdErr)
	}
	return stdOut, stdErr, err
}

func execCommandInPodAndAllowFail(f *framework.Framework, c, ns string, opt *metav1.ListOptions) (string, string) {
	podOpt, err := getCommandInPodOpts(f, c, ns, "", opt)
	if err != nil {
		return "", err.Error()
	}
	stdOut, stdErr, err := f.ExecWithOptions(podOpt)
	if err != nil {
		e2elog.Logf("command %s failed: %v", c, err)
	}
	return stdOut, stdErr
}

func loadApp(path string) (*v1.Pod, error) {
	app := v1.Pod{}
	if err := unmarshal(path, &app); err != nil {
		return nil, err
	}
	for i := range app.Spec.Containers {
		app.Spec.Containers[i].ImagePullPolicy = v1.PullIfNotPresent
	}
	return &app, nil
}

func createApp(c kubernetes.Interface, app *v1.Pod, timeout int) error {
	_, err := c.CoreV1().Pods(app.Namespace).Create(context.TODO(), app, metav1.CreateOptions{})
	if err != nil {
		return fmt.Errorf("failed to create app: %w", err)
	}
	return waitForPodInRunningState(app.Name, app.Namespace, c, timeout, noError)
}

func createAppErr(c kubernetes.Interface, app *v1.Pod, timeout int, errString string) error {
	_, err := c.CoreV1().Pods(app.Namespace).Create(context.TODO(), app, metav1.CreateOptions{})
	if err != nil {
		return err
	}
	return waitForPodInRunningState(app.Name, app.Namespace, c, timeout, errString)
}

func waitForPodInRunningState(name, ns string, c kubernetes.Interface, t int, expectedError string) error {
	timeout := time.Duration(t) * time.Minute
	start := time.Now()
	e2elog.Logf("Waiting up to %v to be in Running state", name)
	return wait.PollImmediate(poll, timeout, func() (bool, error) {
		pod, err := c.CoreV1().Pods(ns).Get(context.TODO(), name, metav1.GetOptions{})
		if err != nil {
			if isRetryableAPIError(err) {
				return false, nil
			}
			return false, fmt.Errorf("failed to get app: %w", err)
		}
		switch pod.Status.Phase {
		case v1.PodRunning:
			return true, nil
		case v1.PodFailed, v1.PodSucceeded:
			return false, conditions.ErrPodCompleted
		case v1.PodPending:
			if expectedError != "" {
				events, err := c.CoreV1().Events(ns).List(context.TODO(), metav1.ListOptions{
					FieldSelector: fmt.Sprintf("involvedObject.name=%s", name),
				})
				if err != nil {
					return false, err
				}
				if strings.Contains(events.String(), expectedError) {
					e2elog.Logf("Expected Error %q found successfully", expectedError)
					return true, err
				}
			}
		case v1.PodUnknown:
			e2elog.Logf(
				"%s app  is in %s phase expected to be in Running  state (%d seconds elapsed)",
				name,
				pod.Status.Phase,
				int(time.Since(start).Seconds()))
		}
		return false, nil
	})
}

func deletePod(name, ns string, c kubernetes.Interface, t int) error {
	timeout := time.Duration(t) * time.Minute
	err := c.CoreV1().Pods(ns).Delete(context.TODO(), name, metav1.DeleteOptions{})
	if err != nil {
		return fmt.Errorf("failed to delete app: %w", err)
	}
	start := time.Now()
	e2elog.Logf("Waiting for pod %v to be deleted", name)
	return wait.PollImmediate(poll, timeout, func() (bool, error) {
		_, err := c.CoreV1().Pods(ns).Get(context.TODO(), name, metav1.GetOptions{})
		if err != nil {
			if isRetryableAPIError(err) {
				return false, nil
			}
			if apierrs.IsNotFound(err) {
				return true, nil
			}
			e2elog.Logf("%s app  to be deleted (%d seconds elapsed)", name, int(time.Since(start).Seconds()))
			return false, fmt.Errorf("failed to get app: %w", err)
		}
		return false, nil
	})
}

func deletePodWithLabel(label, ns string, skipNotFound bool) error {
	_, err := framework.RunKubectl(ns, "delete", "po", "-l", label, fmt.Sprintf("--ignore-not-found=%t", skipNotFound))
	if err != nil {
		e2elog.Logf("failed to delete pod %v", err)
	}
	return err
}

// calculateSHA512sum returns the sha512sum of a file inside a pod.
func calculateSHA512sum(f *framework.Framework, app *v1.Pod, filePath string, opt *metav1.ListOptions) (string, error) {
	cmd := fmt.Sprintf("sha512sum %s", filePath)
	sha512sumOut, stdErr, err := execCommandInPod(f, cmd, app.Namespace, opt)
	if err != nil {
		return "", err
	}
	if stdErr != "" {
		return "", fmt.Errorf("error: sha512sum could not be calculated %v", stdErr)
	}
	// extract checksum from sha512sum output.
	checkSum := strings.Split(sha512sumOut, "")[0]
	e2elog.Logf("Calculated checksum  %s", checkSum)
	return checkSum, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/dsa"
	"crypto/ecdsa"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"
)

var keyUsageStrings = map[x509.KeyUsage]string{
	x509.KeyUsageDigitalSignature:  "Digital Signature",
	x509.KeyUsageContentCommitment: "Content Commitment",
	x509.KeyUsageKeyEncipherment:   "Key Encipherment",
	x509.KeyUsageDataEncipherment:  "Data Encipherment",
	x509.KeyUsageKeyAgreement:      "Key Agreement",
	x509.KeyUsageCertSign:          "Cert Sign",
	x509.KeyUsageCRLSign:           "CRL Sign",
	x509.KeyUsageEncipherOnly:      "Encipher Only",
	x509.KeyUsageDecipherOnly:      "Decipher Only",
}

var extKeyUsageStrings = map[x509.ExtKeyUsage]string{
	x509.ExtKeyUsageAny:                        "Any",
	x509.ExtKeyUsageServerAuth:                 "Server Auth",
	x509.ExtKeyUsageClientAuth:                 "Client Auth",
	x509.ExtKeyUsageCodeSigning:                "Code Signing",
	x509.ExtKeyUsageEmailProtection:            "Email Protection",
	x509.ExtKeyUsageIPSECEndSystem:             "IPSEC End System",
	x509.ExtKeyUsageIPSECTunnel:                "IPSEC Tunnel",
	x509.ExtKeyUsageIPSECUser:                  "IPSEC User",
	x509.ExtKeyUsageTimeStamping:               "Time Stamping",
	x509.ExtKeyUsageOCSPSigning:                "OCSP Signing",
	x509.ExtKeyUsageMicrosoftServerGatedCrypto: "Microsoft ServerGatedCrypto",
	x509.ExtKeyUsageNetscapeServerGatedCrypto:  "Netscape ServerGatedCrypto",
}

var algoName = [...]string{
	x509.MD2WithRSA:      "MD2-RSA",
	x509.MD5WithRSA:      "MD5-RSA",
	x509.SHA1WithRSA:     "SHA1-RSA",
	x509.SHA256WithRSA:   "SHA256-RSA",
	x509.SHA384WithRSA:   "SHA384-RSA",
	x509.SHA512WithRSA:   "SHA512-RSA",
	x509.DSAWithSHA1:     "DSA-SHA1",
	x509.DSAWithSHA256:   "DSA-SHA256",
	x509.ECDSAWithSHA1:   "ECDSA-SHA1",
	x509.ECDSAWithSHA256: "ECDSA-SHA256",
	x509.ECDSAWithSHA384: "ECDSA-SHA384",
	x509.ECDSAWithSHA512: "ECDSA-SHA512",
}

type basicConstraints struct {
	IsCA       bool `json:"is_ca"`
	MaxPathLen *int `json:"pathlen,omitempty"`
}

type nameConstraints struct {
	Critical            bool     `json:"critical"`
	PermittedDNSDomains []string `json:"permitted_dns_domains,omitempty"`
}

type simpleCertificate struct {
	Alias              string              `json:"alias,omitempty"`
	SerialNumber       string              `json:"serial"`
	NotBefore          time.Time           `json:"not_before"`
	NotAfter           time.Time           `json:"not_after"`
	SignatureAlgorithm simpleSigAlg        `json:"signature_algorithm"`
	IsSelfSigned       bool                `json:"is_self_signed"`
	Subject            simplePkixName      `json:"subject"`
	Issuer             simplePkixName      `json:"issuer"`
	BasicConstraints   *basicConstraints   `json:"basic_constraints,omitempty"`
	NameConstraints    *nameConstraints    `json:"name_constraints,omitempty"`
	KeyUsage           simpleKeyUsage      `json:"key_usage,omitempty"`
	ExtKeyUsage        []simpleExtKeyUsage `json:"extended_key_usage,omitempty"`
	AltDNSNames        []string            `json:"dns_names,omitempty"`
	AltIPAddresses     []net.IP            `json:"ip_addresses,omitempty"`
	EmailAddresses     []string            `json:"email_addresses,omitempty"`
	Warnings           []string            `json:"warnings,omitempty"`
}

type simplePkixName struct {
	Name  pkix.Name
	KeyID []byte
}

type simpleKeyUsage x509.KeyUsage
type simpleExtKeyUsage x509.ExtKeyUsage

type simpleSigAlg x509.SignatureAlgorithm

type simpleResult struct {
	Certificates []simpleCertificate `json:"certificates"`
	VerifyResult *simpleVerification `json:"verify_result,omitempty"`
}

func createSimpleCertificate(c certWithName) simpleCertificate {
	out := simpleCertificate{
		Alias:              c.name,
		SerialNumber:       c.cert.SerialNumber.String(),
		NotBefore:          c.cert.NotBefore,
		NotAfter:           c.cert.NotAfter,
		SignatureAlgorithm: simpleSigAlg(c.cert.SignatureAlgorithm),
		IsSelfSigned:       isSelfSigned(c.cert),
		Subject: simplePkixName{
			Name:  c.cert.Subject,
			KeyID: c.cert.SubjectKeyId,
		},
		Issuer: simplePkixName{
			Name:  c.cert.Issuer,
			KeyID: c.cert.AuthorityKeyId,
		},
		KeyUsage:       simpleKeyUsage(c.cert.KeyUsage),
		AltDNSNames:    c.cert.DNSNames,
		AltIPAddresses: c.cert.IPAddresses,
		EmailAddresses: c.cert.EmailAddresses,
		Warnings:       certWarnings(c.cert),
	}

	if c.cert.BasicConstraintsValid {
		out.BasicConstraints = &basicConstraints{
			IsCA: c.cert.IsCA,
		}
		if c.cert.MaxPathLen > 0 || c.cert.MaxPathLenZero {
			out.BasicConstraints.MaxPathLen = &c.cert.MaxPathLen
		}
	}

	if len(c.cert.PermittedDNSDomains) > 0 {
		out.NameConstraints = &nameConstraints{
			Critical:            c.cert.PermittedDNSDomainsCritical,
			PermittedDNSDomains: c.cert.PermittedDNSDomains,
		}
	}

	simpleEku := []simpleExtKeyUsage{}
	for _, eku := range c.cert.ExtKeyUsage {
		simpleEku = append(simpleEku, simpleExtKeyUsage(eku))
	}
	out.ExtKeyUsage = simpleEku

	return out
}

func (c certWithName) MarshalJSON() ([]byte, error) {
	out := createSimpleCertificate(c)
	return json.Marshal(out)
}

func (p simplePkixName) MarshalJSON() ([]byte, error) {
	out := map[string]interface{}{}

	if p.Name.CommonName != "" {
		out["common_name"] = p.Name.CommonName
	}
	if len(p.Name.Organization) > 0 {
		out["organization"] = p.Name.Organization
	}
	if len(p.Name.OrganizationalUnit) > 0 {
		out["organizational_unit"] = p.Name.OrganizationalUnit
	}
	if len(p.Name.Country) > 0 {
		out["country"] = p.Name.Country
	}
	if len(p.Name.Locality) > 0 {
		out["locality"] = p.Name.Locality
	}
	if len(p.KeyID) > 0 {
		out["key_id"] = hexify(p.KeyID)
	}

	return json.Marshal(out)
}

func (k simpleKeyUsage) MarshalJSON() ([]byte, error) {
	return json.Marshal(keyUsage(k))
}

func (e simpleExtKeyUsage) MarshalJSON() ([]byte, error) {
	return json.Marshal(extKeyUsage(e))
}

func (s simpleSigAlg) MarshalJSON() ([]byte, error) {
	return json.Marshal(algString(x509.SignatureAlgorithm(s)))
}

// hexify returns a colon separated, hexadecimal representation
// of a given byte array.
func hexify(arr []byte) string {
	var hexed bytes.Buffer
	for i := 0; i < len(arr); i++ {
		hexed.WriteString(strings.ToUpper(hex.EncodeToString(arr[i : i+1])))
		if i < len(arr)-1 {
			hexed.WriteString(":")
		}
	}
	return hexed.String()
}

// keyUsage decodes/prints key usage from a certificate.
func keyUsage(sKu simpleKeyUsage) []string {
	ku := x509.KeyUsage(sKu)
	out := []string{}
	for key, value := range keyUsageStrings {
		if ku&key > 0 {
			out = append(out, value)
		}
	}
	return out
}

// extKeyUsage decodes/prints extended key usage from a certificate.
func extKeyUsage(sEku simpleExtKeyUsage) string {
	eku := x509.ExtKeyUsage(sEku)
	val, ok := extKeyUsageStrings[eku]
	if ok {
		return val
	}
	return fmt.Sprintf("unknown:%d", eku)
}

func algString(algo x509.SignatureAlgorithm) string {
	if 0 < algo && int(algo) < len(algoName) {
		return algoName[algo]
	}
	return strconv.Itoa(int(algo))
}

// decodeKey returns the algorithm and key size for a public key.
func decodeKey(publicKey interface{}) (string, int) {
	switch publicKey.(type) {
	case *dsa.PublicKey:
		return "DSA", publicKey.(*dsa.PublicKey).P.BitLen()
	case *ecdsa.PublicKey:
		return "ECDSA", publicKey.(*ecdsa.PublicKey).Curve.Params().BitSize
	case *rsa.PublicKey:
		return "RSA", publicKey.(*rsa.PublicKey).N.BitLen()
	default:
		return "", 0
	}
}

// certWarnings prints a list of warnings to show common mistakes in certs.
func certWarnings(cert *x509.Certificate) (warnings []string) {
	if cert.SerialNumber.Sign() != 1 {
		warnings = append(warnings, "Serial number in cert appears to be zero/negative")
	}

	if cert.SerialNumber.BitLen() > 160 {
		warnings = append(warnings, "Serial number too long; should be 20 bytes or less")
	}

	if (cert.KeyUsage&x509.KeyUsageCertSign != 0) && !cert.IsCA {
		warnings = append(warnings, "Key usage 'cert sign' is set, but is not a CA cert")
	}

	if (cert.KeyUsage&x509.KeyUsageCertSign == 0) && cert.IsCA {
		warnings = append(warnings, "Certificate is a CA cert, but key usage 'cert sign' missing")
	}

	if cert.Version < 2 {
		warnings = append(warnings, fmt.Sprintf("Certificate is not in X509v3 format (version is %d)", cert.Version+1))
	}

	if len(cert.UnhandledCriticalExtensions) > 0 {
		warnings = append(warnings, "Certificate has unhandled critical extensions")
	}

	warnings = append(warnings, algWarnings(cert)...)

	return
}

// algWarnings checks key sizes, signature algorithms.
func algWarnings(cert *x509.Certificate) (warnings []string) {
	alg, size := decodeKey(cert.PublicKey)
	if (alg == "RSA" || alg == "DSA") && size < 2048 {
		warnings = append(warnings, fmt.Sprintf("Size of %s key should be at least 2048 bits", alg))
	}
	if alg == "ECDSA" && size < 224 {
		warnings = append(warnings, fmt.Sprintf("Size of %s key should be at least 224 bits", alg))
	}

	for _, alg := range badSignatureAlgorithms {
		if cert.SignatureAlgorithm == alg {
			warnings = append(warnings, fmt.Sprintf("Using %s, which is an outdated signature algorithm", algString(alg)))
		}
	}

	if alg == "RSA" {
		key := cert.PublicKey.(*rsa.PublicKey)
		if key.E < 3 {
			warnings = append(warnings, "Public key exponent in RSA key is less than 3")
		}
		if key.N.Sign() != 1 {
			warnings = append(warnings, "Public key modulus in RSA key appears to be zero/negative")
		}
	}

	return
}
<commit_msg>Resolve more comments<commit_after>package main

import (
	"bytes"
	"crypto/dsa"
	"crypto/ecdsa"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"math/big"
	"net"
	"strconv"
	"strings"
	"time"
)

var keyUsageStrings = map[x509.KeyUsage]string{
	x509.KeyUsageDigitalSignature:  "Digital Signature",
	x509.KeyUsageContentCommitment: "Content Commitment",
	x509.KeyUsageKeyEncipherment:   "Key Encipherment",
	x509.KeyUsageDataEncipherment:  "Data Encipherment",
	x509.KeyUsageKeyAgreement:      "Key Agreement",
	x509.KeyUsageCertSign:          "Cert Sign",
	x509.KeyUsageCRLSign:           "CRL Sign",
	x509.KeyUsageEncipherOnly:      "Encipher Only",
	x509.KeyUsageDecipherOnly:      "Decipher Only",
}

var extKeyUsageStrings = map[x509.ExtKeyUsage]string{
	x509.ExtKeyUsageAny:                        "Any",
	x509.ExtKeyUsageServerAuth:                 "Server Auth",
	x509.ExtKeyUsageClientAuth:                 "Client Auth",
	x509.ExtKeyUsageCodeSigning:                "Code Signing",
	x509.ExtKeyUsageEmailProtection:            "Email Protection",
	x509.ExtKeyUsageIPSECEndSystem:             "IPSEC End System",
	x509.ExtKeyUsageIPSECTunnel:                "IPSEC Tunnel",
	x509.ExtKeyUsageIPSECUser:                  "IPSEC User",
	x509.ExtKeyUsageTimeStamping:               "Time Stamping",
	x509.ExtKeyUsageOCSPSigning:                "OCSP Signing",
	x509.ExtKeyUsageMicrosoftServerGatedCrypto: "Microsoft ServerGatedCrypto",
	x509.ExtKeyUsageNetscapeServerGatedCrypto:  "Netscape ServerGatedCrypto",
}

var algoName = [...]string{
	x509.MD2WithRSA:      "MD2-RSA",
	x509.MD5WithRSA:      "MD5-RSA",
	x509.SHA1WithRSA:     "SHA1-RSA",
	x509.SHA256WithRSA:   "SHA256-RSA",
	x509.SHA384WithRSA:   "SHA384-RSA",
	x509.SHA512WithRSA:   "SHA512-RSA",
	x509.DSAWithSHA1:     "DSA-SHA1",
	x509.DSAWithSHA256:   "DSA-SHA256",
	x509.ECDSAWithSHA1:   "ECDSA-SHA1",
	x509.ECDSAWithSHA256: "ECDSA-SHA256",
	x509.ECDSAWithSHA384: "ECDSA-SHA384",
	x509.ECDSAWithSHA512: "ECDSA-SHA512",
}

type basicConstraints struct {
	IsCA       bool `json:"is_ca"`
	MaxPathLen *int `json:"pathlen,omitempty"`
}

type nameConstraints struct {
	Critical            bool     `json:"critical,omitempty"`
	PermittedDNSDomains []string `json:"permitted_dns_domains,omitempty"`
}

type simpleCertificate struct {
	Alias              string              `json:"alias,omitempty"`
	SerialNumber       *big.Int            `json:"serial,string"`
	NotBefore          time.Time           `json:"not_before"`
	NotAfter           time.Time           `json:"not_after"`
	SignatureAlgorithm simpleSigAlg        `json:"signature_algorithm"`
	IsSelfSigned       bool                `json:"is_self_signed"`
	Subject            simplePkixName      `json:"subject"`
	Issuer             simplePkixName      `json:"issuer"`
	BasicConstraints   *basicConstraints   `json:"basic_constraints,omitempty"`
	NameConstraints    *nameConstraints    `json:"name_constraints,omitempty"`
	KeyUsage           simpleKeyUsage      `json:"key_usage,omitempty"`
	ExtKeyUsage        []simpleExtKeyUsage `json:"extended_key_usage,omitempty"`
	AltDNSNames        []string            `json:"dns_names,omitempty"`
	AltIPAddresses     []net.IP            `json:"ip_addresses,omitempty"`
	EmailAddresses     []string            `json:"email_addresses,omitempty"`
	Warnings           []string            `json:"warnings,omitempty"`
}

type simplePkixName struct {
	Name  pkix.Name
	KeyID []byte
}

type simpleKeyUsage x509.KeyUsage
type simpleExtKeyUsage x509.ExtKeyUsage

type simpleSigAlg x509.SignatureAlgorithm

type simpleResult struct {
	Certificates []simpleCertificate `json:"certificates"`
	VerifyResult *simpleVerification `json:"verify_result,omitempty"`
}

func createSimpleCertificate(c certWithName) simpleCertificate {
	out := simpleCertificate{
		Alias:              c.name,
		SerialNumber:       c.cert.SerialNumber,
		NotBefore:          c.cert.NotBefore,
		NotAfter:           c.cert.NotAfter,
		SignatureAlgorithm: simpleSigAlg(c.cert.SignatureAlgorithm),
		IsSelfSigned:       isSelfSigned(c.cert),
		Subject: simplePkixName{
			Name:  c.cert.Subject,
			KeyID: c.cert.SubjectKeyId,
		},
		Issuer: simplePkixName{
			Name:  c.cert.Issuer,
			KeyID: c.cert.AuthorityKeyId,
		},
		KeyUsage:       simpleKeyUsage(c.cert.KeyUsage),
		AltDNSNames:    c.cert.DNSNames,
		AltIPAddresses: c.cert.IPAddresses,
		EmailAddresses: c.cert.EmailAddresses,
		Warnings:       certWarnings(c.cert),
	}

	if c.cert.BasicConstraintsValid {
		out.BasicConstraints = &basicConstraints{
			IsCA: c.cert.IsCA,
		}
		if c.cert.MaxPathLen > 0 || c.cert.MaxPathLenZero {
			out.BasicConstraints.MaxPathLen = &c.cert.MaxPathLen
		}
	}

	if len(c.cert.PermittedDNSDomains) > 0 {
		out.NameConstraints = &nameConstraints{
			Critical:            c.cert.PermittedDNSDomainsCritical,
			PermittedDNSDomains: c.cert.PermittedDNSDomains,
		}
	}

	simpleEku := []simpleExtKeyUsage{}
	for _, eku := range c.cert.ExtKeyUsage {
		simpleEku = append(simpleEku, simpleExtKeyUsage(eku))
	}
	out.ExtKeyUsage = simpleEku

	return out
}

func (c certWithName) MarshalJSON() ([]byte, error) {
	out := createSimpleCertificate(c)
	return json.Marshal(out)
}

func (p simplePkixName) MarshalJSON() ([]byte, error) {
	out := map[string]interface{}{}

	if p.Name.CommonName != "" {
		out["common_name"] = p.Name.CommonName
	}
	if len(p.Name.Organization) > 0 {
		out["organization"] = p.Name.Organization
	}
	if len(p.Name.OrganizationalUnit) > 0 {
		out["organizational_unit"] = p.Name.OrganizationalUnit
	}
	if len(p.Name.Country) > 0 {
		out["country"] = p.Name.Country
	}
	if len(p.Name.Locality) > 0 {
		out["locality"] = p.Name.Locality
	}
	if len(p.KeyID) > 0 {
		out["key_id"] = hexify(p.KeyID)
	}

	return json.Marshal(out)
}

func (k simpleKeyUsage) MarshalJSON() ([]byte, error) {
	return json.Marshal(keyUsage(k))
}

func (e simpleExtKeyUsage) MarshalJSON() ([]byte, error) {
	return json.Marshal(extKeyUsage(e))
}

func (s simpleSigAlg) MarshalJSON() ([]byte, error) {
	return json.Marshal(algString(x509.SignatureAlgorithm(s)))
}

// hexify returns a colon separated, hexadecimal representation
// of a given byte array.
func hexify(arr []byte) string {
	var hexed bytes.Buffer
	for i := 0; i < len(arr); i++ {
		hexed.WriteString(strings.ToUpper(hex.EncodeToString(arr[i : i+1])))
		if i < len(arr)-1 {
			hexed.WriteString(":")
		}
	}
	return hexed.String()
}

// keyUsage decodes/prints key usage from a certificate.
func keyUsage(sKu simpleKeyUsage) []string {
	ku := x509.KeyUsage(sKu)
	out := []string{}
	for key, value := range keyUsageStrings {
		if ku&key > 0 {
			out = append(out, value)
		}
	}
	return out
}

// extKeyUsage decodes/prints extended key usage from a certificate.
func extKeyUsage(sEku simpleExtKeyUsage) string {
	eku := x509.ExtKeyUsage(sEku)
	val, ok := extKeyUsageStrings[eku]
	if ok {
		return val
	}
	return fmt.Sprintf("unknown:%d", eku)
}

func algString(algo x509.SignatureAlgorithm) string {
	if 0 < algo && int(algo) < len(algoName) {
		return algoName[algo]
	}
	return strconv.Itoa(int(algo))
}

// decodeKey returns the algorithm and key size for a public key.
func decodeKey(publicKey interface{}) (string, int) {
	switch publicKey.(type) {
	case *dsa.PublicKey:
		return "DSA", publicKey.(*dsa.PublicKey).P.BitLen()
	case *ecdsa.PublicKey:
		return "ECDSA", publicKey.(*ecdsa.PublicKey).Curve.Params().BitSize
	case *rsa.PublicKey:
		return "RSA", publicKey.(*rsa.PublicKey).N.BitLen()
	default:
		return "", 0
	}
}

// certWarnings prints a list of warnings to show common mistakes in certs.
func certWarnings(cert *x509.Certificate) (warnings []string) {
	if cert.SerialNumber.Sign() != 1 {
		warnings = append(warnings, "Serial number in cert appears to be zero/negative")
	}

	if cert.SerialNumber.BitLen() > 160 {
		warnings = append(warnings, "Serial number too long; should be 20 bytes or less")
	}

	if (cert.KeyUsage&x509.KeyUsageCertSign != 0) && !cert.IsCA {
		warnings = append(warnings, "Key usage 'cert sign' is set, but is not a CA cert")
	}

	if (cert.KeyUsage&x509.KeyUsageCertSign == 0) && cert.IsCA {
		warnings = append(warnings, "Certificate is a CA cert, but key usage 'cert sign' missing")
	}

	if cert.Version < 2 {
		warnings = append(warnings, fmt.Sprintf("Certificate is not in X509v3 format (version is %d)", cert.Version+1))
	}

	if len(cert.UnhandledCriticalExtensions) > 0 {
		warnings = append(warnings, "Certificate has unhandled critical extensions")
	}

	warnings = append(warnings, algWarnings(cert)...)

	return
}

// algWarnings checks key sizes, signature algorithms.
func algWarnings(cert *x509.Certificate) (warnings []string) {
	alg, size := decodeKey(cert.PublicKey)
	if (alg == "RSA" || alg == "DSA") && size < 2048 {
		warnings = append(warnings, fmt.Sprintf("Size of %s key should be at least 2048 bits", alg))
	}
	if alg == "ECDSA" && size < 224 {
		warnings = append(warnings, fmt.Sprintf("Size of %s key should be at least 224 bits", alg))
	}

	for _, alg := range badSignatureAlgorithms {
		if cert.SignatureAlgorithm == alg {
			warnings = append(warnings, fmt.Sprintf("Using %s, which is an outdated signature algorithm", algString(alg)))
		}
	}

	if alg == "RSA" {
		key := cert.PublicKey.(*rsa.PublicKey)
		if key.E < 3 {
			warnings = append(warnings, "Public key exponent in RSA key is less than 3")
		}
		if key.N.Sign() != 1 {
			warnings = append(warnings, "Public key modulus in RSA key appears to be zero/negative")
		}
	}

	return
}
<|endoftext|>


<commit_before>package main

import (
	log "code.google.com/p/log4go"
	"time"
)

const (
	// handshake
	OP_HANDSHAKE       = int32(0)
	OP_HANDSHAKE_REPLY = int32(1)
	// heartbeat
	OP_HEARTBEAT       = int32(2)
	OP_HEARTBEAT_REPLY = int32(3)
	// send text messgae
	OP_SEND_SMS       = int32(4)
	OP_SEND_SMS_REPLY = int32(5)
	// kick user
	OP_DISCONNECT_REPLY = int32(6)
	// auth user
	OP_AUTH       = int32(7)
	OP_AUTH_REPLY = int32(8)

	// for test
	OP_TEST       = int32(254)
	OP_TEST_REPLY = int32(255)
)

type Operator interface {
	// Operate process the common operation such as send message etc.
	Operate(*Proto) error
	// Connect used for auth user and return a sub key & hearbeat.
	Connect(*Proto) (string, time.Duration, error)
	// Disconnect used for revoke the subkey.
	Disconnect(string) error
}

type DefaultOperator struct {
}

func (operator *DefaultOperator) Operate(proto *Proto) error {
	if proto.Operation == OP_SEND_SMS {
		// call suntao's api
		// proto.Body = nil

		proto.Operation = OP_SEND_SMS_REPLY
		log.Info("send sms proto: %v", proto)
	} else if proto.Operation == OP_TEST {
		// TODO remove
		log.Debug("test operation: %s", proto.Body)
		proto.Operation = OP_TEST_REPLY
		proto.Body = []byte("reply test")
	} else {
		return ErrOperation
	}
	return nil
}

func (operator *DefaultOperator) Connect(proto *Proto) (subKey string, heartbeat time.Duration, err error) {
	// TODO call register router
	// for test
	subKey = string(proto.Body)
	heartbeat = 60 * time.Second
	return
}

func (operator *DefaultOperator) Disconnect(subKey string) error {
	return nil
}
<commit_msg>init repo<commit_after>package main

import (
	log "code.google.com/p/log4go"
	"time"
)

const (
	// handshake
	OP_HANDSHAKE       = int32(0)
	OP_HANDSHAKE_REPLY = int32(1)
	// heartbeat
	OP_HEARTBEAT       = int32(2)
	OP_HEARTBEAT_REPLY = int32(3)
	// send text messgae
	OP_SEND_SMS       = int32(4)
	OP_SEND_SMS_REPLY = int32(5)
	// kick user
	OP_DISCONNECT_REPLY = int32(6)
	// auth user
	OP_AUTH       = int32(7)
	OP_AUTH_REPLY = int32(8)

	// for test
	OP_TEST       = int32(254)
	OP_TEST_REPLY = int32(255)
)

type Operator interface {
	// Operate process the common operation such as send message etc.
	Operate(*Proto) error
	// Connect used for auth user and return a sub key & hearbeat.
	Connect(*Proto) (string, time.Duration, error)
	// Disconnect used for revoke the subkey.
	Disconnect(string) error
}

type DefaultOperator struct {
}

func (operator *DefaultOperator) Operate(proto *Proto) error {
	if proto.Operation == OP_SEND_SMS {
		// call suntao's api
		// proto.Body = nil

		proto.Operation = OP_SEND_SMS_REPLY
		log.Info("send sms proto: %v", proto)
	} else if proto.Operation == OP_TEST {
		// TODO remove
		log.Debug("test operation: %s", proto.Body)
		proto.Operation = OP_TEST_REPLY
		proto.Body = proto.Body
	} else {
		return ErrOperation
	}
	return nil
}

func (operator *DefaultOperator) Connect(proto *Proto) (subKey string, heartbeat time.Duration, err error) {
	// TODO call register router
	// for test
	subKey = string(proto.Body)
	heartbeat = 60 * time.Second
	return
}

func (operator *DefaultOperator) Disconnect(subKey string) error {
	return nil
}
<|endoftext|>


<commit_before>package command

import (
	"bufio"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"os/exec"
	"path/filepath"
	"strings"
)

// Command is our structured data/object for Command
type Command struct {
	alias      string
	command    string
	verbose    bool
	workingdir string
}

const pathDrush = "/usr/local/bin/drush"

// NewDrushCommand creates a new container for []Command objects
func NewDrushCommand() *Command {
	return &Command{}
}

// Set changes all given values for a Drush command object.
func (drush *Command) Set(alias string, command string, verbose bool) {
	drush.alias = alias
	drush.command = command
	drush.verbose = verbose
	drush.workingdir = "."
}

// GetWorkingDir returns the specified working directory used with executed Drush commands.
func (drush *Command) GetWorkingDir() string {
	return drush.workingdir
}

// SetWorkingDir sets the specified working directory used with executed Drush commands.
func (drush *Command) SetWorkingDir(value string) {
	drush.workingdir = value
}

// GetAlias returns the alias used to executed Drush commands.
func (drush *Command) GetAlias() string {
	return drush.alias
}

// SetAlias changes the alias used to executed Drush commands.
func (drush *Command) SetAlias(value string) {
	drush.alias = value
}

// GetCommand returns the command string on executed Drush commands.
func (drush *Command) GetCommand() string {
	return drush.command
}

// SetCommand changes the command string on executed Drush commands.
func (drush *Command) SetCommand(value string) {
	drush.command = value
}

// GetVerbose returns the verbosity setting on executed Drush commands.
func (drush *Command) GetVerbose() bool {
	return drush.verbose
}

// SetVerbose changes the verbosity setting on executed Drush commands.
func (drush *Command) SetVerbose(value bool) {
	drush.verbose = value
}

// LiveOutput returns, and prints the live output of the executing program
// This will wait for completion before proceeding.
func (drush *Command) LiveOutput() error {
	if strings.Contains(drush.alias, "@") == true {
		drush.alias = strings.Replace(drush.alias, "@", "", -1)
	}
	if drush.alias != "" {
		drush.alias = fmt.Sprintf("@%v", drush.alias)
	}
	if drush.verbose == true {
		drush.alias = fmt.Sprintf("%v --verbose", drush.alias)
	}
	args := fmt.Sprintf("%v %v", drush.alias, drush.command)

	comm := new(exec.Cmd)
	comm = exec.Command("sh", "-c", "cd "+drush.workingdir+" && "+pathDrush+" "+args)
	Pipe, _ := comm.StderrPipe()
	scanner := bufio.NewScanner(Pipe)
	go func() {
		for scanner.Scan() {
			if strings.Contains(scanner.Text(), "[error]") || strings.Contains(scanner.Text(), "[warning]") {
				log.Warnf("%s", scanner.Text())
			} else {
				log.Infof("%s", scanner.Text())
			}
		}
	}()
	err := comm.Start()
	err = comm.Wait()
	return err
}

// Output gets the output from a single Command object, does not support []Command items.
func (drush *Command) Output() ([]string, error) {
	comm, err := drush.Run()
	response := filepath.SplitList(string(comm))
	return response, err
}

// CombinedOutput will return the CombinedOutput of a command.
func (drush *Command) CombinedOutput() ([]byte, error) {
	if strings.Contains(drush.alias, "@") == true {
		drush.alias = strings.Replace(drush.alias, "@", "", -1)
	}
	if drush.alias != "" {
		drush.alias = fmt.Sprintf("@%v", drush.alias)
	}
	if drush.verbose == true {
		drush.alias = fmt.Sprintf("%v --verbose", drush.alias)
	}
	args := fmt.Sprintf("%v %v", drush.alias, drush.command)
	if drush.GetWorkingDir() != "." {
		comm, err := exec.Command("sh", "-c", "cd "+drush.workingdir+" && "+pathDrush+" "+args).CombinedOutput()
		return comm, err
	}
	comm, err := exec.Command("sh", "-c", pathDrush+" "+args).CombinedOutput()
	return comm, err
}

// Run runs an individual Command object, does not support []Command items.
func (drush *Command) Run() ([]byte, error) {
	if strings.Contains(drush.alias, "@") == true {
		drush.alias = strings.Replace(drush.alias, "@", "", -1)
	}
	if drush.alias != "" {
		drush.alias = fmt.Sprintf("@%v", drush.alias)
	}
	if drush.verbose == true {
		drush.alias = fmt.Sprintf("%v --verbose", drush.alias)
	}
	args := fmt.Sprintf("%v %v", drush.alias, drush.command)
	if drush.GetWorkingDir() != "." {
		comm, err := exec.Command("sh", "-c", "cd "+drush.workingdir+" && "+pathDrush+" "+args).CombinedOutput()
		return comm, err
	}
	comm, err := exec.Command("sh", "-c", pathDrush+" "+args).CombinedOutput()
	return comm, err
}

// DrushDatabaseSync executes a database synchronisation task from a source to destination with the use of Drush.
func DrushDatabaseSync(srcAlias, destAlias string) {
	/* So our binary and this function combined support two-way traffic...  */
	x := NewDrushCommand()
	srcAlias = strings.Replace(srcAlias, "@", "", -1)
	destAlias = strings.Replace(destAlias, "@", "", -1)
	x.Set("", fmt.Sprintf("sql-sync @%v @%v -y", srcAlias, destAlias), true)
	_, err := x.Output()
	if err == nil {
		log.Infoln("Syncronised databases complete.")
	} else {
		log.Errorln("Could not syncronise databases.")
	}
}

// DrushFilesSync executes a file synchronisation task from a source to destination with the use of Drush.
func DrushFilesSync(srcAlias, destAlias string) {
	x := NewDrushCommand()
	srcAlias = strings.Replace(srcAlias, "@", "", -1)
	destAlias = strings.Replace(destAlias, "@", "", -1)
	x.Set("", fmt.Sprintf("--yes rsync --exclude-other-sites --exclude-conf @%v:%%files @%v:%%files", srcAlias, destAlias), true)
	_, err := x.Output()
	if err == nil {
		log.Infoln("Synced public file system.")
	} else {
		log.Warnln("Public file system has not been synced.")
	}
	x.Set("", fmt.Sprintf("--yes rsync --exclude-other-sites --exclude-conf @%v:%%private @%v:%%private", srcAlias, destAlias), true)
	_, err = x.Output()
	if err == nil {
		log.Infoln("Synced private file system.")
	} else {
		log.Warnln("Private file system has not been synced.")
	}
}

// DrushClearCache performs a cache clear task on an input site alias with the use of Drush.
func DrushClearCache(alias string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set(alias, "cc all", false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not clear caches.", err)
	} else {
		log.Infoln("Caches cleared.")
	}
}

// DrushRebuildRegistry performs a registry rebuild task on an input site alias with the use of Drush.
func DrushRebuildRegistry(alias string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set(alias, "rr", false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not rebuild registry.", err)
	} else {
		log.Infoln("Rebuilt registry.")
	}
}

// DrushUpdateDatabase performs a database update task on an input site alias with the use of Drush.
func DrushUpdateDatabase(alias string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set(alias, "updb -y", false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not update database.", err)
	} else {
		log.Infoln("Updated database where possible.")
	}
}

// DrushDownloadToPath performs a database update task on an input site alias with the use of Drush.
func DrushDownloadToPath(path, project string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set("", "pm-download --yes "+project+" --destination="+path, false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not download module ", project, err)
	} else {
		log.Infoln("Downloaded module", project)
	}
}

// DrushDownloadToAlias performs a database update task on an input site alias with the use of Drush.
func DrushDownloadToAlias(alias, project string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set(alias, "pm-download --yes "+project, false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not download module ", project, err)
	} else {
		log.Infoln("Downloaded module", project)
	}
}

// DrushVariableSet Runs drush vset with a given variable name and value.
func DrushVariableSet(alias, variable_name, variable_value string) {
	srcAlias := strings.Replace(alias, "@", "", -1)
	x := NewDrushCommand()
	x.Set(srcAlias, fmt.Sprintf("vset %v %v", variable_name, variable_value), true)
	drushOut, err := x.Output()
	if err == nil {
		log.Infof("Succesfully set %v to %v via Drush\n", variable_name, variable_value)
	} else {
		log.Errorf("Could not set %v to %v via Drush: %v\n", variable_name, variable_value, drushOut)
	}
}

// DrushVariableGet Runs drush vset with a given variable name and value.
func DrushVariableGet(alias, variable_name string) string {
	srcAlias := strings.Replace(alias, "@", "", -1)
	x := NewDrushCommand()
	x.Set(srcAlias, fmt.Sprintf("vget --exact %v", variable_name), false)
	drushOut, err := x.Output()
	drushOutString := fmt.Sprintf("%s", drushOut)
	if strings.Contains(drushOutString, "No matching variable found") {
		log.Warnf("Variable %v was not found", variable_name)
	} else if err == nil {
		log.Infof("Succesfully retreived %v via Drush\n", variable_name)
		drushOutString = strings.Replace(drushOutString, "[", "", -1)
		drushOutString = strings.Replace(drushOutString, "]", "", -1)
		drushOutString = strings.Replace(drushOutString, "\n", "", -1)
		return drushOutString
	} else {
		log.Errorf("Could not retreived %v via Drush: %v\n", variable_name, drushOut)
	}
	return ""
}<commit_msg>#22: Improve reporting messages/documentation.<commit_after>package command

import (
	"bufio"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"os/exec"
	"path/filepath"
	"strings"
)

// Command is our structured data/object for Command
type Command struct {
	alias      string
	command    string
	verbose    bool
	workingdir string
}

const pathDrush = "/usr/local/bin/drush"

// NewDrushCommand creates a new container for []Command objects
func NewDrushCommand() *Command {
	return &Command{}
}

// Set changes all given values for a Drush command object.
func (drush *Command) Set(alias string, command string, verbose bool) {
	drush.alias = alias
	drush.command = command
	drush.verbose = verbose
	drush.workingdir = "."
}

// GetWorkingDir returns the specified working directory used with executed Drush commands.
func (drush *Command) GetWorkingDir() string {
	return drush.workingdir
}

// SetWorkingDir sets the specified working directory used with executed Drush commands.
func (drush *Command) SetWorkingDir(value string) {
	drush.workingdir = value
}

// GetAlias returns the alias used to executed Drush commands.
func (drush *Command) GetAlias() string {
	return drush.alias
}

// SetAlias changes the alias used to executed Drush commands.
func (drush *Command) SetAlias(value string) {
	drush.alias = value
}

// GetCommand returns the command string on executed Drush commands.
func (drush *Command) GetCommand() string {
	return drush.command
}

// SetCommand changes the command string on executed Drush commands.
func (drush *Command) SetCommand(value string) {
	drush.command = value
}

// GetVerbose returns the verbosity setting on executed Drush commands.
func (drush *Command) GetVerbose() bool {
	return drush.verbose
}

// SetVerbose changes the verbosity setting on executed Drush commands.
func (drush *Command) SetVerbose(value bool) {
	drush.verbose = value
}

// LiveOutput returns, and prints the live output of the executing program
// This will wait for completion before proceeding.
func (drush *Command) LiveOutput() error {
	if strings.Contains(drush.alias, "@") == true {
		drush.alias = strings.Replace(drush.alias, "@", "", -1)
	}
	if drush.alias != "" {
		drush.alias = fmt.Sprintf("@%v", drush.alias)
	}
	if drush.verbose == true {
		drush.alias = fmt.Sprintf("%v --verbose", drush.alias)
	}
	args := fmt.Sprintf("%v %v", drush.alias, drush.command)

	comm := new(exec.Cmd)
	comm = exec.Command("sh", "-c", "cd "+drush.workingdir+" && "+pathDrush+" "+args)
	Pipe, _ := comm.StderrPipe()
	scanner := bufio.NewScanner(Pipe)
	go func() {
		for scanner.Scan() {
			if strings.Contains(scanner.Text(), "[error]") || strings.Contains(scanner.Text(), "[warning]") {
				log.Warnf("%s", scanner.Text())
			} else {
				log.Infof("%s", scanner.Text())
			}
		}
	}()
	err := comm.Start()
	err = comm.Wait()
	return err
}

// Output gets the output from a single Command object, does not support []Command items.
func (drush *Command) Output() ([]string, error) {
	comm, err := drush.Run()
	response := filepath.SplitList(string(comm))
	return response, err
}

// CombinedOutput will return the CombinedOutput of a command.
func (drush *Command) CombinedOutput() ([]byte, error) {
	if strings.Contains(drush.alias, "@") == true {
		drush.alias = strings.Replace(drush.alias, "@", "", -1)
	}
	if drush.alias != "" {
		drush.alias = fmt.Sprintf("@%v", drush.alias)
	}
	if drush.verbose == true {
		drush.alias = fmt.Sprintf("%v --verbose", drush.alias)
	}
	args := fmt.Sprintf("%v %v", drush.alias, drush.command)
	if drush.GetWorkingDir() != "." {
		comm, err := exec.Command("sh", "-c", "cd "+drush.workingdir+" && "+pathDrush+" "+args).CombinedOutput()
		return comm, err
	}
	comm, err := exec.Command("sh", "-c", pathDrush+" "+args).CombinedOutput()
	return comm, err
}

// Run runs an individual Command object, does not support []Command items.
func (drush *Command) Run() ([]byte, error) {
	if strings.Contains(drush.alias, "@") == true {
		drush.alias = strings.Replace(drush.alias, "@", "", -1)
	}
	if drush.alias != "" {
		drush.alias = fmt.Sprintf("@%v", drush.alias)
	}
	if drush.verbose == true {
		drush.alias = fmt.Sprintf("%v --verbose", drush.alias)
	}
	args := fmt.Sprintf("%v %v", drush.alias, drush.command)
	if drush.GetWorkingDir() != "." {
		comm, err := exec.Command("sh", "-c", "cd "+drush.workingdir+" && "+pathDrush+" "+args).CombinedOutput()
		return comm, err
	}
	comm, err := exec.Command("sh", "-c", pathDrush+" "+args).CombinedOutput()
	return comm, err
}

// DrushDatabaseSync executes a database synchronisation task from a source to destination with the use of Drush.
func DrushDatabaseSync(srcAlias, destAlias string) {
	/* So our binary and this function combined support two-way traffic...  */
	x := NewDrushCommand()
	srcAlias = strings.Replace(srcAlias, "@", "", -1)
	destAlias = strings.Replace(destAlias, "@", "", -1)
	x.Set("", fmt.Sprintf("sql-sync @%v @%v -y", srcAlias, destAlias), true)
	_, err := x.Output()
	if err == nil {
		log.Infoln("Syncronised databases complete.")
	} else {
		log.Errorln("Could not syncronise databases.")
	}
}

// DrushFilesSync executes a file synchronisation task from a source to destination with the use of Drush.
func DrushFilesSync(srcAlias, destAlias string) {
	x := NewDrushCommand()
	srcAlias = strings.Replace(srcAlias, "@", "", -1)
	destAlias = strings.Replace(destAlias, "@", "", -1)
	x.Set("", fmt.Sprintf("--yes rsync --exclude-other-sites --exclude-conf @%v:%%files @%v:%%files", srcAlias, destAlias), true)
	_, err := x.Output()
	if err == nil {
		log.Infoln("Synced public file system.")
	} else {
		log.Warnln("Public file system has not been synced.")
	}
	x.Set("", fmt.Sprintf("--yes rsync --exclude-other-sites --exclude-conf @%v:%%private @%v:%%private", srcAlias, destAlias), true)
	_, err = x.Output()
	if err == nil {
		log.Infoln("Synced private file system.")
	} else {
		log.Warnln("Private file system has not been synced.")
	}
}

// DrushClearCache performs a cache clear task on an input site alias with the use of Drush.
func DrushClearCache(alias string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set(alias, "cc all", false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not clear caches.", err)
	} else {
		log.Infoln("Caches cleared.")
	}
}

// DrushRebuildRegistry performs a registry rebuild task on an input site alias with the use of Drush.
func DrushRebuildRegistry(alias string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set(alias, "rr", false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not rebuild registry.", err)
	} else {
		log.Infoln("Rebuilt registry.")
	}
}

// DrushUpdateDatabase performs a database update task on an input site alias with the use of Drush.
func DrushUpdateDatabase(alias string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set(alias, "updb -y", false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not update database.", err)
	} else {
		log.Infoln("Updated database where possible.")
	}
}

// DrushDownloadToPath performs a database update task on an input site alias with the use of Drush.
func DrushDownloadToPath(path, project string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set("", "pm-download --yes "+project+" --destination="+path, false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not download module ", project, err)
	} else {
		log.Infoln("Downloaded module", project)
	}
}

// DrushDownloadToAlias performs a database update task on an input site alias with the use of Drush.
func DrushDownloadToAlias(alias, project string) {
	drushCommand := NewDrushCommand()
	drushCommand.Set(alias, "pm-download --yes "+project, false)
	_, err := drushCommand.Output()
	if err != nil {
		log.Warnln("Could not download module ", project, err)
	} else {
		log.Infoln("Downloaded module", project)
	}
}

// DrushVariableSet Runs drush vset with a given variable name and value.
func DrushVariableSet(alias, variable_name, variable_value string) {
	srcAlias := strings.Replace(alias, "@", "", -1)
	x := NewDrushCommand()
	x.Set(srcAlias, fmt.Sprintf("vset %v %v", variable_name, variable_value), false)
	drushOut, err := x.Output()
	if err == nil {
		log.Infof("Succesfully set %v to %v via Drush", variable_name, variable_value)
	} else {
		log.Errorf("Could not set %v to %v via Drush: %v", variable_name, variable_value, drushOut)
	}
}

// DrushVariableGet Runs drush vget with an exact variable name from the alias.
func DrushVariableGet(alias, variable_name string) string {
	srcAlias := strings.Replace(alias, "@", "", -1)
	x := NewDrushCommand()
	x.Set(srcAlias, fmt.Sprintf("vget --exact %v", variable_name), false)
	drushOut, err := x.Output()
	drushOutString := fmt.Sprintf("%s", drushOut)
	if strings.Contains(drushOutString, "No matching variable found") {
		log.Warnf("Variable %v was not found", variable_name)
	} else if err == nil {
		log.Infof("Succesfully retreived %v via Drush", variable_name)
		drushOutString = strings.Replace(drushOutString, "[", "", -1)
		drushOutString = strings.Replace(drushOutString, "]", "", -1)
		drushOutString = strings.Replace(drushOutString, "\n", "", -1)
		return drushOutString
	} else {
		log.Errorf("Could not retreived %v via Drush: %v", variable_name, drushOut)
	}
	return ""
}<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"net/http"
	"sync"
	"time"

	"golang.org/x/net/context"

	"github.com/codegangsta/cli"
	"github.com/golang/glog"
	"github.com/rs/xhandler"

	"tower.pro/renderer/compiler"
	"tower.pro/renderer/renderweb"
	"tower.pro/renderer/storage"
	"tower.pro/renderer/watcher"

	// Profiler
	_ "net/http/pprof"
)

// DefaultWebOptions - Default renderweb options.
// You can append options here like renderweb.WithMiddleware.
var DefaultWebOptions = []renderweb.Option{
	// It means we won't spit out component JSON, just HTML
	// in case of API routes like one using json.encode they
	// will still work as expected with no difference
	renderweb.WithAlwaysHTML(true),
}

// Commands - List of renderer commands.
var Commands = []cli.Command{
	Web,
}

// Web - Web command.
var Web = cli.Command{
	Name:  "web",
	Usage: "starts renderer web API",
	Flags: []cli.Flag{
		// Compiler options
		cli.StringSliceFlag{
			Name:  "routes",
			Usage: "file containing routes in yaml format",
		},
		cli.StringFlag{
			Name:  "components",
			Usage: "directory containing components",
		},
		cli.BoolFlag{
			Name:  "watch",
			Usage: "watch for changes in components",
		},
		cli.BoolFlag{
			Name:  "compress",
			Usage: "removes repeated whitespaces",
		},
		cli.DurationFlag{
			Name:  "cache-expiration",
			Usage: "cache expiration time",
			Value: 15 * time.Minute,
		},
		cli.DurationFlag{
			Name:  "cache-cleanup",
			Usage: "cache cleanup interval",
			Value: 5 * time.Minute,
		},

		// Web server options
		cli.StringFlag{
			Name:  "listen-addr",
			Usage: "web interface listening address",
			Value: "127.0.0.1:6660",
		},
		cli.DurationFlag{
			Name:  "render-timeout",
			Usage: "component render timeout",
			Value: 5 * time.Second,
		},

		// HTTP server flags
		cli.DurationFlag{
			Name:   "http-read-timeout",
			EnvVar: "HTTP_READ_TIMEOUT",
			Usage:  "http server read timeout",
			Value:  time.Minute,
		},
		cli.DurationFlag{
			Name:   "http-write-timeout",
			EnvVar: "HTTP_WRITE_TIMEOUT",
			Usage:  "http server write timeout",
			Value:  time.Minute,
		},

		// Profiler
		cli.StringFlag{
			Name:   "pprof-addr",
			EnvVar: "PPROF_ADDR",
			Usage:  "pprof listening address",
		},

		// Tracing
		cli.BoolFlag{
			Name:   "tracing-enable",
			EnvVar: "TRACING_ENABLE",
			Usage:  "enable tracing",
		},
	},
	Action: func(c *cli.Context) {
		// Get components directory from --components flag
		// Print fatal error if not set
		if c.String("components") == "" {
			glog.Fatal("--components flag cannot be empty")
		}

		// Create a new storage in directory from --components flag
		storage, err := storage.New(
			storage.WithDir(c.String("components")),
			storage.WithCacheExpiration(c.Duration("cache-expiration")),
			storage.WithCacheCleanupInterval(c.Duration("cache-cleanup")),
			storage.WithWhitespaceRemoval(c.Bool("compress")),
		)
		if err != nil {
			glog.Fatalf("[storage] %v", err)
		}
		defer storage.Close()

		// Create a compiler from storage
		comp := compiler.New(storage)

		// Create a context with compiler
		ctx := compiler.NewContext(context.Background(), comp)

		if c.Bool("tracing-enable") {
			DefaultWebOptions = append(DefaultWebOptions, renderweb.WithTracing())
		}

		// Turn routes into HTTP handler
		api, err := constructHandler(c.StringSlice("routes"), DefaultWebOptions)
		if err != nil {
			glog.Fatalf("[routes] %v", err)
		}

		// Construct API handler
		handler := &atomicHandler{
			Context:  ctx,
			Current:  xhandler.New(ctx, api),
			Options:  DefaultWebOptions,
			Watching: c.Bool("watch"),
			Routes:   c.StringSlice("routes"),
			Mutex:    new(sync.RWMutex),
		}

		if c.Bool("watch") {
			// Start watching for changes in components directory
			var w *watcher.Watcher
			w, err = watcher.Start(c.String("components"), storage)
			if err != nil {
				glog.Fatal(err)
			}
			defer w.Stop()

			// Start watching for changes in routes
			for _, filename := range c.StringSlice("routes") {
				var watch *watcher.Watcher
				watch, err = watcher.Start(filename, handler)
				if err != nil {
					glog.Fatal(err)
				}
				defer watch.Stop()
			}
		}

		// Start profiler if enabled
		if pprofaddr := c.String("pprof-addr"); pprofaddr != "" {
			go func() {
				glog.Infof("[pprof] starting listener on %s", pprofaddr)
				if err := http.ListenAndServe(pprofaddr, nil); err != nil {
					glog.Fatal(err)
				}
			}()
		}

		// Construct http server
		server := &http.Server{
			Addr:           c.String("listen-addr"),
			Handler:        handler,
			ReadTimeout:    c.Duration("http-read-timeout"),
			WriteTimeout:   c.Duration("http-write-timeout"),
			MaxHeaderBytes: 64 * 1024,
		}

		glog.Infof("[server] starting listener on %s", c.String("listen-addr"))
		if err = server.ListenAndServe(); err != nil {
			glog.Fatalf("[server] %v", err)
		}
	},
}

type atomicHandler struct {
	Context context.Context
	Current http.Handler
	Options []renderweb.Option

	Mutex    *sync.RWMutex
	Watching bool
	Routes   []string
}

// FlushCache - Flushes routes cache. Reads them and constructs handler.
func (handler *atomicHandler) FlushCache() {
	// Construct handler from routes
	h, err := handler.construct()
	if err != nil {
		glog.Fatalf("[routes] %v", err)
	}

	// Lock mutex and exchange handler
	handler.Mutex.Lock()
	handler.Current = h
	handler.Mutex.Unlock()
}

func (handler *atomicHandler) construct() (_ http.Handler, err error) {
	h, err := constructHandler(handler.Routes, handler.Options)
	if err != nil {
		return
	}
	return xhandler.New(handler.Context, h), nil
}

func (handler *atomicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// If not watching don't use mutexe
	if !handler.Watching {
		handler.Current.ServeHTTP(w, r)
		return
	}

	// Lock for read and get handler
	handler.Mutex.RLock()
	h := handler.Current
	handler.Mutex.RUnlock()

	// Serve request
	h.ServeHTTP(w, r)
}

func constructHandler(filenames []string, options []renderweb.Option) (_ xhandler.HandlerC, err error) {
	if len(filenames) == 0 {
		return renderweb.New(), nil
	}

	routes, err := constructRoutes(filenames, options)
	if err != nil {
		return
	}

	// Turn routes into HTTP handler
	return routes.Construct(options...)
}

// constructRoutes - Constructs routes map from multiple filenames.
func constructRoutes(filenames []string, options []renderweb.Option) (res renderweb.Routes, err error) {
	res = make(renderweb.Routes)
	for _, filename := range filenames {
		var routes renderweb.Routes
		routes, err = renderweb.RoutesFromFile(filename)
		if err != nil {
			return
		}
		for route, handler := range routes {
			if _, exists := res[route]; exists {
				return nil, fmt.Errorf("route %q in %q is not unique", route, filename)
			}
			res[route] = handler
		}
	}
	return
}
<commit_msg>command flags etc<commit_after>package command

import (
	"fmt"
	"net/http"
	"sync"
	"time"

	"golang.org/x/net/context"

	"github.com/codegangsta/cli"
	"github.com/golang/glog"
	"github.com/rs/xhandler"

	"tower.pro/renderer/compiler"
	"tower.pro/renderer/renderer"
	"tower.pro/renderer/storage"
	"tower.pro/renderer/watcher"

	// Profiler
	_ "net/http/pprof"
)

// DefaultWebOptions - Default renderer options.
// You can append options here like renderer.WithMiddleware.
var DefaultWebOptions = []renderer.Option{
	// It means we won't spit out component JSON, just HTML
	// in case of API routes like one using json.encode they
	// will still work as expected with no difference
	renderer.WithAlwaysHTML(true),
}

// Commands - List of renderer commands.
var Commands = []cli.Command{
	Web,
}

// Web - Web command.
var Web = cli.Command{
	Name:  "server",
	Usage: "renderer server",
	Flags: []cli.Flag{
		// Compiler options
		cli.StringSliceFlag{
			Name:  "routes",
			Usage: "file containing routes in yaml format",
		},
		cli.StringFlag{
			Name:  "components",
			Usage: "directory containing components",
		},
		cli.BoolFlag{
			Name:  "watch",
			Usage: "watch for changes in components",
		},
		cli.BoolFlag{
			Name:  "compress",
			Usage: "removes repeated whitespaces",
		},
		cli.DurationFlag{
			Name:  "cache-expiration",
			Usage: "cache expiration time",
			Value: 15 * time.Minute,
		},
		cli.DurationFlag{
			Name:  "cache-cleanup",
			Usage: "cache cleanup interval",
			Value: 5 * time.Minute,
		},

		// Web server options
		cli.StringFlag{
			Name:  "listen-addr",
			Usage: "renderer interface listening address",
			Value: "127.0.0.1:6660",
		},
		cli.DurationFlag{
			Name:  "render-timeout",
			Usage: "component render timeout",
			Value: 5 * time.Second,
		},

		// HTTP server flags
		cli.DurationFlag{
			Name:   "renderer-read-timeout",
			EnvVar: "RENDERER_READ_TIMEOUT",
			Usage:  "renderer server read timeout",
			Value:  time.Minute,
		},
		cli.DurationFlag{
			Name:   "renderer-write-timeout",
			EnvVar: "RENDERER_WRITE_TIMEOUT",
			Usage:  "renderer server write timeout",
			Value:  time.Minute,
		},

		// Tracing and profiling
		cli.StringFlag{
			Name:   "debug-addr",
			EnvVar: "DEBUG_ADDR",
			Usage:  "debug listening address",
		},
		cli.BoolFlag{
			Name:   "tracing",
			EnvVar: "TRACING",
			Usage:  "enable tracing (use with --debug-addr)",
		},
	},
	Action: func(c *cli.Context) {
		// Get components directory from --components flag
		// Print fatal error if not set
		if c.String("components") == "" {
			glog.Fatal("--components flag cannot be empty")
		}

		// Create a new storage in directory from --components flag
		storage, err := storage.New(
			storage.WithDir(c.String("components")),
			storage.WithCacheExpiration(c.Duration("cache-expiration")),
			storage.WithCacheCleanupInterval(c.Duration("cache-cleanup")),
			storage.WithWhitespaceRemoval(c.Bool("compress")),
		)
		if err != nil {
			glog.Fatalf("[storage] %v", err)
		}
		defer storage.Close()

		// Create a compiler from storage
		comp := compiler.New(storage)

		// Create a context with compiler
		ctx := compiler.NewContext(context.Background(), comp)

		if c.Bool("tracing") {
			DefaultWebOptions = append(DefaultWebOptions, renderer.WithTracing())
		}

		// Turn routes into HTTP handler
		api, err := constructHandler(c.StringSlice("routes"), DefaultWebOptions)
		if err != nil {
			glog.Fatalf("[routes] %v", err)
		}

		// Construct API handler
		handler := &atomicHandler{
			Context:  ctx,
			Current:  xhandler.New(ctx, api),
			Options:  DefaultWebOptions,
			Watching: c.Bool("watch"),
			Routes:   c.StringSlice("routes"),
			Mutex:    new(sync.RWMutex),
		}

		if c.Bool("watch") {
			// Start watching for changes in components directory
			var w *watcher.Watcher
			w, err = watcher.Start(c.String("components"), storage)
			if err != nil {
				glog.Fatal(err)
			}
			defer w.Stop()

			// Start watching for changes in routes
			for _, filename := range c.StringSlice("routes") {
				var watch *watcher.Watcher
				watch, err = watcher.Start(filename, handler)
				if err != nil {
					glog.Fatal(err)
				}
				defer watch.Stop()
			}
		}

		// Start profiler if enabled
		if addr := c.String("pprof-addr"); addr != "" {
			go debugServer(addr)
		}

		// Construct http server
		server := &http.Server{
			Addr:           c.String("listen-addr"),
			Handler:        handler,
			ReadTimeout:    c.Duration("http-read-timeout"),
			WriteTimeout:   c.Duration("http-write-timeout"),
			MaxHeaderBytes: 64 * 1024,
		}

		glog.Infof("[renderer] starting server on %s", c.String("listen-addr"))
		if err = server.ListenAndServe(); err != nil {
			glog.Fatalf("[renderer] %v", err)
		}
	},
}

type atomicHandler struct {
	Context context.Context
	Current http.Handler
	Options []renderer.Option

	Mutex    *sync.RWMutex
	Watching bool
	Routes   []string
}

// FlushCache - Flushes routes cache. Reads them and constructs handler.
func (handler *atomicHandler) FlushCache() {
	// Construct handler from routes
	h, err := handler.construct()
	if err != nil {
		glog.Fatalf("[routes] %v", err)
	}

	// Lock mutex and exchange handler
	handler.Mutex.Lock()
	handler.Current = h
	handler.Mutex.Unlock()
}

func (handler *atomicHandler) construct() (_ http.Handler, err error) {
	h, err := constructHandler(handler.Routes, handler.Options)
	if err != nil {
		return
	}
	return xhandler.New(handler.Context, h), nil
}

func (handler *atomicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// If not watching don't use mutexe
	if !handler.Watching {
		handler.Current.ServeHTTP(w, r)
		return
	}

	// Lock for read and get handler
	handler.Mutex.RLock()
	h := handler.Current
	handler.Mutex.RUnlock()

	// Serve request
	h.ServeHTTP(w, r)
}

func constructHandler(filenames []string, options []renderer.Option) (_ xhandler.HandlerC, err error) {
	if len(filenames) == 0 {
		return renderer.New(), nil
	}

	routes, err := constructRoutes(filenames, options)
	if err != nil {
		return
	}

	// Turn routes into HTTP handler
	return routes.Construct(options...)
}

// constructRoutes - Constructs routes map from multiple filenames.
func constructRoutes(filenames []string, options []renderer.Option) (res renderer.Routes, err error) {
	res = make(renderer.Routes)
	for _, filename := range filenames {
		var routes renderer.Routes
		routes, err = renderer.RoutesFromFile(filename)
		if err != nil {
			return
		}
		for route, handler := range routes {
			if _, exists := res[route]; exists {
				return nil, fmt.Errorf("route %q in %q is not unique", route, filename)
			}
			res[route] = handler
		}
	}
	return
}

func debugServer(addr string) {
	glog.Infof("[debug] starting server on %s", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		glog.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/jim/monk"
	"path"
  "flag"
  "strings"
  "os"
)

type searchPaths []string
var searchPathsFlag searchPaths

func (sp *searchPaths) Set(searchPath string) error {
    if !strings.HasPrefix(searchPath, "/") {
	    dir, err := os.Getwd()
      if err != nil {
        return err
      }
      searchPath = path.Join(dir, searchPath)
    }
    *sp = append(*sp, searchPath)
    return nil
}

func (sp *searchPaths) String() string {
  return strings.Join(*sp, ",")
}

func init() {
  flag.Var(&searchPathsFlag, "s", "path to search for assets when building")
}

func main() {
  flag.Parse()

  if flag.NArg() == 0 {
    printUsage()
    return
  }

	r := &monk.Resolution{}
	context := monk.NewContext(monk.DiskFS{})

  if len(searchPathsFlag) == 0 {
    panic("You must specify at least one path using -s")
  }

  for _, sPath := range searchPathsFlag {
    context.SearchPath(sPath)
  }

  if flag.NArg() == 0 {
    panic("You must specify the asset to build.")
  }
  asset := flag.Arg(0)

	err := r.Resolve(asset, context)

	if err != nil {
		panic(err)
	}

	for _, resolved := range r.Resolved {
		fmt.Printf("%s ", resolved)
	}
	fmt.Println()

	built := monk.Build(r, context)
	fmt.Println(built)
}

func printUsage() {
  fmt.Println("monk, a tool to build assets")
  fmt.Println("  usage: monk [OPTIONS] asset_to_build.ext\n")
  flag.PrintDefaults()
}
<commit_msg>Don’t print out resolved paths when building a file.<commit_after>package main

import (
	"fmt"
	"github.com/jim/monk"
	"path"
  "flag"
  "strings"
  "os"
)

type searchPaths []string
var searchPathsFlag searchPaths

func (sp *searchPaths) Set(searchPath string) error {
    if !strings.HasPrefix(searchPath, "/") {
	    dir, err := os.Getwd()
      if err != nil {
        return err
      }
      searchPath = path.Join(dir, searchPath)
    }
    *sp = append(*sp, searchPath)
    return nil
}

func (sp *searchPaths) String() string {
  return strings.Join(*sp, ",")
}

func init() {
  flag.Var(&searchPathsFlag, "s", "path to search for assets when building")
}

func main() {
  flag.Parse()

  if flag.NArg() == 0 {
    printUsage()
    return
  }

	r := &monk.Resolution{}
	context := monk.NewContext(monk.DiskFS{})

  if len(searchPathsFlag) == 0 {
    panic("You must specify at least one path using -s")
  }

  for _, sPath := range searchPathsFlag {
    context.SearchPath(sPath)
  }

  if flag.NArg() == 0 {
    panic("You must specify the asset to build.")
  }
  asset := flag.Arg(0)

	err := r.Resolve(asset, context)

	if err != nil {
		panic(err)
	}

	built := monk.Build(r, context)
	fmt.Println(built)
}

func printUsage() {
  fmt.Println("monk, a tool to build assets")
  fmt.Println("  usage: monk [OPTIONS] asset_to_build.ext\n")
  flag.PrintDefaults()
}
<|endoftext|>


<commit_before>package command

import (
	"flag"
	"fmt"
	"github.com/mitchellh/cli"
	"strings"
)

// MembersCommand is a Command implementation that queries a running
// Serf agent what members are part of the cluster currently.
type MembersCommand struct {
	Ui cli.Ui
}

func (c *MembersCommand) Help() string {
	helpText := `
Usage: serf members [options]

  Outputs the members of a running Serf agent.

Options:

  -detailed                 Additional information such as protocol verions
                            will be shown.
  -rpc-addr=127.0.0.1:7373  RPC address of the Serf agent.
`
	return strings.TrimSpace(helpText)
}

func (c *MembersCommand) Run(args []string) int {
	var detailed bool
	cmdFlags := flag.NewFlagSet("members", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
	cmdFlags.BoolVar(&detailed, "detailed", false, "detailed output")
	rpcAddr := RPCAddrFlag(cmdFlags)
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	client, err := RPCClient(*rpcAddr)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error connecting to Serf agent: %s", err))
		return 1
	}
	defer client.Close()

	members, err := client.Members()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error retrieving members: %s", err))
		return 1
	}

	for _, member := range members {
		c.Ui.Output(fmt.Sprintf("%s    %s    %s    %s",
			member.Name, member.Addr, member.Status, member.Role))

		if detailed {
			c.Ui.Output(fmt.Sprintf("    Protocol Version: %d",
				member.DelegateCur))
			c.Ui.Output(fmt.Sprintf("    Available Protocol Range: [%d, %d]",
				member.DelegateMin, member.DelegateMax))
		}
	}

	return 0
}

func (c *MembersCommand) Synopsis() string {
	return "Lists the members of a Serf cluster"
}
<commit_msg>command/memebers: Expose port, format IPv6 nicely<commit_after>package command

import (
	"flag"
	"fmt"
	"github.com/mitchellh/cli"
	"net"
	"strings"
)

// MembersCommand is a Command implementation that queries a running
// Serf agent what members are part of the cluster currently.
type MembersCommand struct {
	Ui cli.Ui
}

func (c *MembersCommand) Help() string {
	helpText := `
Usage: serf members [options]

  Outputs the members of a running Serf agent.

Options:

  -detailed                 Additional information such as protocol verions
                            will be shown.
  -rpc-addr=127.0.0.1:7373  RPC address of the Serf agent.
`
	return strings.TrimSpace(helpText)
}

func (c *MembersCommand) Run(args []string) int {
	var detailed bool
	cmdFlags := flag.NewFlagSet("members", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
	cmdFlags.BoolVar(&detailed, "detailed", false, "detailed output")
	rpcAddr := RPCAddrFlag(cmdFlags)
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	client, err := RPCClient(*rpcAddr)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error connecting to Serf agent: %s", err))
		return 1
	}
	defer client.Close()

	members, err := client.Members()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error retrieving members: %s", err))
		return 1
	}

	for _, member := range members {
		addr := net.TCPAddr{IP: member.Addr, Port: int(member.Port)}
		c.Ui.Output(fmt.Sprintf("%s    %s    %s    %s",
			member.Name, addr.String(), member.Status, member.Role))

		if detailed {
			c.Ui.Output(fmt.Sprintf("    Protocol Version: %d",
				member.DelegateCur))
			c.Ui.Output(fmt.Sprintf("    Available Protocol Range: [%d, %d]",
				member.DelegateMin, member.DelegateMax))
		}
	}

	return 0
}

func (c *MembersCommand) Synopsis() string {
	return "Lists the members of a Serf cluster"
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"log"
	"time"

	"github.com/igungor/tlbot"
	"golang.org/x/net/context"
)

func init() {
	// XXX: enable them when the time comes.
	// populate()
	// register(cmdPrayerCall)
	// register(cmdFoodFast)
	// register(cmdFoodDawn)
}

var (
	cmdPrayerCall = &Command{
		Name:      "okundumu",
		ShortLine: "is it read?",
		Run:       runPrayerCall,
	}
	cmdFoodFast = &Command{
		Name:      "iftar",
		ShortLine: "seninle iftar ediyorum",
		Run:       runFoodFast,
	}
	cmdFoodDawn = &Command{
		Name:      "sahur",
		ShortLine: "sahura kalkti mi?",
		Run:       runFoodDawn,
	}
)

const (
	timeFormat     = "2 Jan 2006"
	timeFormatLong = "2 Jan 2006 15:04"
	timezone       = "Europe/Istanbul"
)

var noes = []string{
	"hayır",
	"hayır.",
	"Hayır",
	"Hayır.",
	"no",
	"no.",
	"NO.",
	"NO!",
	"NO",
	"nope",
	"nicht",
	"okunmadı",
	"hayır okunmadı",
}

type timePair struct {
	iftar time.Time
	sahur time.Time
}

var callTime = map[string]timePair{}

var _callTime = map[string]struct {
	iftar, sahur string
}{
	"18 Jun 2015": {"20:48", "03:22"},
	"19 Jun 2015": {"20:48", "03:22"},
	"20 Jun 2015": {"20:48", "03:22"},
	"21 Jun 2015": {"20:48", "03:22"},
	"22 Jun 2015": {"20:49", "03:23"},
	"23 Jun 2015": {"20:49", "03:23"},
	"24 Jun 2015": {"20:49", "03:23"},
	"25 Jun 2015": {"20:49", "03:23"},
	"26 Jun 2015": {"20:49", "03:24"},
	"27 Jun 2015": {"20:49", "03:24"},
	"28 Jun 2015": {"20:49", "03:25"},
	"29 Jun 2015": {"20:49", "03:26"},
	"30 Jun 2015": {"20:49", "03:26"},
	"1 Jul 2015":  {"20:49", "03:27"},
	"2 Jul 2015":  {"20:49", "03:28"},
	"3 Jul 2015":  {"20:49", "03:28"},
	"4 Jul 2015":  {"20:49", "03:29"},
	"5 Jul 2015":  {"20:48", "03:30"},
	"6 Jul 2015":  {"20:48", "03:31"},
	"7 Jul 2015":  {"20:48", "03:32"},
	"8 Jul 2015":  {"20:48", "03:33"},
	"9 Jul 2015":  {"20:47", "03:35"},
	"10 Jul 2015": {"20:47", "03:35"},
	"11 Jul 2015": {"20:46", "03:37"},
	"12 Jul 2015": {"20:46", "03:38"},
	"13 Jul 2015": {"20:46", "03:39"},
	"14 Jul 2015": {"20:45", "03:40"},
	"15 Jul 2015": {"20:44", "03:41"},
	"16 Jul 2015": {"20:44", "03:43"},
}

func populate() {
	loc, _ := time.LoadLocation(timezone)

	for k, v := range _callTime {
		iftar, _ := time.ParseInLocation(timeFormatLong, fmt.Sprintf("%v %v", k, v.iftar), loc)
		sahur, _ := time.ParseInLocation(timeFormatLong, fmt.Sprintf("%v %v", k, v.sahur), loc)

		callTime[k] = timePair{iftar, sahur}
	}
}

func runPrayerCall(ctx context.Context, b *tlbot.Bot, msg *tlbot.Message) {
	loc, _ := time.LoadLocation(timezone)

	now := time.Now().In(loc)
	nowstr := now.Format(timeFormat)

	timepair, ok := callTime[nowstr]
	var txt string
	switch {
	case !ok:
		txt = "galiba oruç bitti"
	case now.After(timepair.iftar):
		txt = "okundu"
	case now.After(timepair.sahur) && now.Hour() < 6:
		txt = "sahur okundu ama iftara daha çok var"
	case now.Before(timepair.sahur):
		txt = "sahur henüz okunmadı"
	default:
		// after sahur and before iftar, hence NO
		txt = randChoice(noes)
	}

	err := b.SendMessage(msg.Chat.ID, txt, tlbot.ModeNone, false, nil)
	if err != nil {
		log.Printf("Error while sending message. Err: %v\n", err)
		return
	}
}

func runFoodFast(ctx context.Context, b *tlbot.Bot, msg *tlbot.Message) {
	loc, _ := time.LoadLocation(timezone)

	now := time.Now().In(loc)
	nowstr := now.Format(timeFormat)

	timepair, ok := callTime[nowstr]
	var txt string
	if ok {
		txt = timepair.iftar.Format("15:04")
	} else {
		txt = "galiba oruç bitti"
	}

	err := b.SendMessage(msg.Chat.ID, txt, tlbot.ModeNone, false, nil)
	if err != nil {
		log.Printf("Error while sending message. Err: %v\n", err)
		return
	}
}

func runFoodDawn(ctx context.Context, b *tlbot.Bot, msg *tlbot.Message) {
	loc, _ := time.LoadLocation(timezone)

	now := time.Now().In(loc)
	nowstr := now.Format(timeFormat)

	timepair, ok := callTime[nowstr]
	var txt string
	if ok {
		txt = timepair.sahur.Format("15:04")
	} else {
		txt = "galiba oruç bitti"
	}

	err := b.SendMessage(msg.Chat.ID, txt, tlbot.ModeNone, false, nil)
	if err != nil {
		log.Printf("Error while sending message. Err: %v\n", err)
		return
	}
}
<commit_msg>ramadan: add 2016 iftar,sahur times<commit_after>package command

import (
	"fmt"
	"log"
	"time"

	"github.com/igungor/tlbot"
	"golang.org/x/net/context"
)

func init() {
	// XXX: enable them when the time comes.
	// populate()
	// register(cmdPrayerCall)
	// register(cmdFoodFast)
	// register(cmdFoodDawn)
}

var (
	cmdPrayerCall = &Command{
		Name:      "okundumu",
		ShortLine: "is it read?",
		Run:       runPrayerCall,
	}
	cmdFoodFast = &Command{
		Name:      "iftar",
		ShortLine: "seninle iftar ediyorum",
		Run:       runFoodFast,
	}
	cmdFoodDawn = &Command{
		Name:      "sahur",
		ShortLine: "sahura kalkti mi?",
		Run:       runFoodDawn,
	}
)

const (
	timeFormat     = "2 Jan 2006"
	timeFormatLong = "2 Jan 2006 15:04"
	timezone       = "Europe/Istanbul"
)

var noes = []string{
	"hayır",
	"hayır.",
	"Hayır",
	"Hayır.",
	"no",
	"no.",
	"NO.",
	"NO!",
	"NO",
	"nope",
	"nicht",
	"okunmadı",
	"hayır okunmadı",
}

type timePair struct {
	iftar time.Time
	sahur time.Time
}

var callTime = map[string]timePair{}

var _callTime = map[string]struct {
	iftar, sahur string
}{
	"18 Jun 2015": {"20:48", "03:22"},
	"19 Jun 2015": {"20:48", "03:22"},
	"20 Jun 2015": {"20:48", "03:22"},
	"21 Jun 2015": {"20:48", "03:22"},
	"22 Jun 2015": {"20:49", "03:23"},
	"23 Jun 2015": {"20:49", "03:23"},
	"24 Jun 2015": {"20:49", "03:23"},
	"25 Jun 2015": {"20:49", "03:23"},
	"26 Jun 2015": {"20:49", "03:24"},
	"27 Jun 2015": {"20:49", "03:24"},
	"28 Jun 2015": {"20:49", "03:25"},
	"29 Jun 2015": {"20:49", "03:26"},
	"30 Jun 2015": {"20:49", "03:26"},
	"1 Jul 2015":  {"20:49", "03:27"},
	"2 Jul 2015":  {"20:49", "03:28"},
	"3 Jul 2015":  {"20:49", "03:28"},
	"4 Jul 2015":  {"20:49", "03:29"},
	"5 Jul 2015":  {"20:48", "03:30"},
	"6 Jul 2015":  {"20:48", "03:31"},
	"7 Jul 2015":  {"20:48", "03:32"},
	"8 Jul 2015":  {"20:48", "03:33"},
	"9 Jul 2015":  {"20:47", "03:35"},
	"10 Jul 2015": {"20:47", "03:35"},
	"11 Jul 2015": {"20:46", "03:37"},
	"12 Jul 2015": {"20:46", "03:38"},
	"13 Jul 2015": {"20:46", "03:39"},
	"14 Jul 2015": {"20:45", "03:40"},
	"15 Jul 2015": {"20:44", "03:41"},
	"16 Jul 2015": {"20:44", "03:43"},

	"6 Jun 2016":  {"20:41", "03:26"},
	"7 Jun 2016":  {"20:42", "03:26"},
	"8 Jun 2016":  {"20:43", "03:25"},
	"9 Jun 2016":  {"20:43", "03:25"},
	"10 Jun 2016": {"20:44", "03:24"},
	"11 Jun 2016": {"20:44", "03:24"},
	"12 Jun 2016": {"20:45", "03:23"},
	"13 Jun 2016": {"20:45", "03:23"},
	"14 Jun 2016": {"20:46", "03:23"},
	"15 Jun 2016": {"20:46", "03:23"},
	"16 Jun 2016": {"20:46", "03:23"},
	"17 Jun 2016": {"20:47", "03:23"},
	"18 Jun 2016": {"20:47", "03:23"},
	"19 Jun 2016": {"20:47", "03:23"},
	"20 Jun 2016": {"20:48", "03:23"},
	"21 Jun 2016": {"20:48", "03:23"},
	"22 Jun 2016": {"20:48", "03:23"},
	"23 Jun 2016": {"20:48", "03:24"},
	"24 Jun 2016": {"20:48", "03:24"},
	"25 Jun 2016": {"20:49", "03:24"},
	"26 Jun 2016": {"20:49", "03:25"},
	"27 Jun 2016": {"20:49", "03:25"},
	"28 Jun 2016": {"20:49", "03:26"},
	"29 Jun 2016": {"20:49", "03:27"},
	"30 Jun 2016": {"20:49", "03:27"},
	"1 Jul 2016":  {"20:48", "03:28"},
	"2 Jul 2016":  {"20:48", "03:29"},
	"3 Jul 2016":  {"20:48", "03:30"},
	"4 Jul 2016":  {"20:48", "03:31"},
}

func populate() {
	loc, _ := time.LoadLocation(timezone)

	for k, v := range _callTime {
		iftar, _ := time.ParseInLocation(timeFormatLong, fmt.Sprintf("%v %v", k, v.iftar), loc)
		sahur, _ := time.ParseInLocation(timeFormatLong, fmt.Sprintf("%v %v", k, v.sahur), loc)

		callTime[k] = timePair{iftar, sahur}
	}
}

func runPrayerCall(ctx context.Context, b *tlbot.Bot, msg *tlbot.Message) {
	loc, _ := time.LoadLocation(timezone)

	now := time.Now().In(loc)
	nowstr := now.Format(timeFormat)

	timepair, ok := callTime[nowstr]
	var txt string
	switch {
	case !ok:
		txt = "galiba oruç bitti"
	case now.After(timepair.iftar):
		txt = "okundu"
	case now.After(timepair.sahur) && now.Hour() < 6:
		txt = "sahur okundu ama iftara daha çok var"
	case now.Before(timepair.sahur):
		txt = "sahur henüz okunmadı"
	default:
		// after sahur and before iftar, hence NO
		txt = randChoice(noes)
	}

	err := b.SendMessage(msg.Chat.ID, txt, tlbot.ModeNone, false, nil)
	if err != nil {
		log.Printf("Error while sending message. Err: %v\n", err)
		return
	}
}

func runFoodFast(ctx context.Context, b *tlbot.Bot, msg *tlbot.Message) {
	loc, _ := time.LoadLocation(timezone)

	now := time.Now().In(loc)
	nowstr := now.Format(timeFormat)

	timepair, ok := callTime[nowstr]
	var txt string
	if ok {
		txt = timepair.iftar.Format("15:04")
	} else {
		txt = "galiba oruç bitti"
	}

	err := b.SendMessage(msg.Chat.ID, txt, tlbot.ModeNone, false, nil)
	if err != nil {
		log.Printf("Error while sending message. Err: %v\n", err)
		return
	}
}

func runFoodDawn(ctx context.Context, b *tlbot.Bot, msg *tlbot.Message) {
	loc, _ := time.LoadLocation(timezone)

	now := time.Now().In(loc)
	nowstr := now.Format(timeFormat)

	timepair, ok := callTime[nowstr]
	var txt string
	if ok {
		txt = timepair.sahur.Format("15:04")
	} else {
		txt = "galiba oruç bitti"
	}

	err := b.SendMessage(msg.Chat.ID, txt, tlbot.ModeNone, false, nil)
	if err != nil {
		log.Printf("Error while sending message. Err: %v\n", err)
		return
	}
}
<|endoftext|>