<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"syscall"

	"gopkg.in/urfave/cli.v1"
)

const (
	kubectl          = "kubectl"
	k8sNamespace     = "gophr"
	k8sDevContext    = "minikube"
	k8sSecretsName   = "gophr-secrets"
	k8sNamespaceFlag = "--namespace=gophr"
)

// K8SPod is a kubernetes pod.
type K8SPod struct {
	Status   K8SPodStatus   `json:"status"`
	Metadata K8SPodMetadata `json:"metadata"`
}

// K8SPodList is a list of kubernetes pods.
type K8SPodList struct {
	Pods []K8SPod `json:"items"`
}

// K8SPodStatus is the status of a kubernetes pod.
type K8SPodStatus struct {
	Phase string `json:"phase"`
}

// K8SPodMetadata is the metadata of a kubernetes pod.
type K8SPodMetadata struct {
	Name string `json:"name"`
}

var (
	serviceK8SFileRegex  = regexp.MustCompile(`service\.[a-z]+\.yml$`)
	prodK8SImageURLRegex = regexp.MustCompile(`gcr\.io/([a-zA-Z0-9\-]+)/([a-zA-Z0-9\-:\.]+)`)
)

func isPersistentK8SResource(k8sfile string) bool {
	return serviceK8SFileRegex.MatchString(k8sfile)
}

func readK8SProdContext(c *cli.Context) (string, error) {
	context := c.GlobalString(flagNameK8SProdContext)
	if len(context) < 1 {
		return context, errors.New("The kubernetes production context must be specified for this command to function.")
	}

	return context, nil
}

// Returns the old kubernetes context, whether the context needs to be switched
// back, and the error.
func switchK8SContext(newK8SContext string, switchingBack bool) (string, bool, error) {
	// First, get the current context.
	output, err := exec.Command(kubectl, "config", "current-context").CombinedOutput()
	if err != nil {
		return "", false, err
	}

	// Save the old context, so that we can return it later.
	oldK8SContext := strings.TrimSpace(string(output[:]))

	// If the k8s context is already switched, then return.
	if newK8SContext == oldK8SContext {
		return oldK8SContext, false, nil
	}

	// Only say something if the context is changing.
	if switchingBack {
		startSpinner(fmt.Sprintf("Switching back to the \"%s\" kubernetes context", newK8SContext))
	} else {
		startSpinner(fmt.Sprintf("Switching to the \"%s\" kubernetes context", newK8SContext))
	}

	// Switch to the new context.
	_, err = exec.Command(kubectl, "config", "use-context", newK8SContext).CombinedOutput()
	if err != nil {
		stopSpinner(false)
		return "", false, err
	}

	stopSpinner(true)
	return oldK8SContext, true, nil
}

func runInK8S(c *cli.Context, fn func() error) error {
	var (
		err                      error
		oldK8SContext            string
		mustSwitchK8SContextBack bool

		env        = readEnvironment(c)
		k8sContext = k8sDevContext
	)

	// If the environment is prod, change the kubernetes context accordingly.
	if env == environmentProd {
		// Read the production context before continuing.
		if k8sContext, err = readK8SProdContext(c); err != nil {
			return err
		}
	}

	// Switch the kubernetes context before continuing.
	if oldK8SContext, mustSwitchK8SContextBack, err = switchK8SContext(k8sContext, false); err != nil {
		return err
	} else if mustSwitchK8SContextBack {
		// If a message was printed, add a new line for padding.
		fmt.Println()
	}

	// Make sure we have a namespace before doing anything else.
	if err = assertNamespaceInK8S(); err != nil {
		return err
	}

	// Check if the secrets are here. If not, scream & shout.
	if !secretsExistInK8S() {
		return errors.New("The gophr secrets have not been installed yet. Use `gophrctl secrets cycle` to correct that.")
	}

	// Execute fn now that the context has been switched.
	if err = fn(); err != nil {
		// Before returning with an error, return the context back to where it was.
		if mustSwitchK8SContextBack {
			if _, _, switchErr := switchK8SContext(oldK8SContext, true); switchErr != nil {
				printError("Failed to reset the kubernetes context:", switchErr)
			}
		}

		return err
	}

	// Switch the context back, error out if there was a problem switching.
	if mustSwitchK8SContextBack {<commit_msg>fixed the secret chicken & egg problem<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"syscall"

	"gopkg.in/urfave/cli.v1"
)

const (
	kubectl          = "kubectl"
	k8sNamespace     = "gophr"
	k8sDevContext    = "minikube"
	k8sSecretsName   = "gophr-secrets"
	k8sNamespaceFlag = "--namespace=gophr"
)

// K8SPod is a kubernetes pod.
type K8SPod struct {
	Status   K8SPodStatus   `json:"status"`
	Metadata K8SPodMetadata `json:"metadata"`
}

// K8SPodList is a list of kubernetes pods.
type K8SPodList struct {
	Pods []K8SPod `json:"items"`
}

// K8SPodStatus is the status of a kubernetes pod.
type K8SPodStatus struct {
	Phase string `json:"phase"`
}

// K8SPodMetadata is the metadata of a kubernetes pod.
type K8SPodMetadata struct {
	Name string `json:"name"`
}

var (
	serviceK8SFileRegex  = regexp.MustCompile(`service\.[a-z]+\.yml$`)
	prodK8SImageURLRegex = regexp.MustCompile(`gcr\.io/([a-zA-Z0-9\-]+)/([a-zA-Z0-9\-:\.]+)`)
)

func isPersistentK8SResource(k8sfile string) bool {
	return serviceK8SFileRegex.MatchString(k8sfile)
}

func readK8SProdContext(c *cli.Context) (string, error) {
	context := c.GlobalString(flagNameK8SProdContext)
	if len(context) < 1 {
		return context, errors.New("The kubernetes production context must be specified for this command to function.")
	}

	return context, nil
}

// Returns the old kubernetes context, whether the context needs to be switched
// back, and the error.
func switchK8SContext(newK8SContext string, switchingBack bool) (string, bool, error) {
	// First, get the current context.
	output, err := exec.Command(kubectl, "config", "current-context").CombinedOutput()
	if err != nil {
		return "", false, err
	}

	// Save the old context, so that we can return it later.
	oldK8SContext := strings.TrimSpace(string(output[:]))

	// If the k8s context is already switched, then return.
	if newK8SContext == oldK8SContext {
		return oldK8SContext, false, nil
	}

	// Only say something if the context is changing.
	if switchingBack {
		startSpinner(fmt.Sprintf("Switching back to the \"%s\" kubernetes context", newK8SContext))
	} else {
		startSpinner(fmt.Sprintf("Switching to the \"%s\" kubernetes context", newK8SContext))
	}

	// Switch to the new context.
	_, err = exec.Command(kubectl, "config", "use-context", newK8SContext).CombinedOutput()
	if err != nil {
		stopSpinner(false)
		return "", false, err
	}

	stopSpinner(true)
	return oldK8SContext, true, nil
}

func runInK8S(c *cli.Context, fn func() error) error {
	var (
		err                      error
		oldK8SContext            string
		mustSwitchK8SContextBack bool

		env        = readEnvironment(c)
		k8sContext = k8sDevContext
	)

	// If the environment is prod, change the kubernetes context accordingly.
	if env == environmentProd {
		// Read the production context before continuing.
		if k8sContext, err = readK8SProdContext(c); err != nil {
			return err
		}
	}

	// Switch the kubernetes context before continuing.
	if oldK8SContext, mustSwitchK8SContextBack, err = switchK8SContext(k8sContext, false); err != nil {
		return err
	} else if mustSwitchK8SContextBack {
		// If a message was printed, add a new line for padding.
		fmt.Println()
	}

	// Make sure we have a namespace before doing anything else.
	if err = assertNamespaceInK8S(); err != nil {
		return err
	}

	// Check if the secrets are here. If not, scream & shout.
	if c.Command.FullName() != "secrets cycle" && !secretsExistInK8S() {
		return errors.New("The gophr secrets have not been installed yet. Use `gophrctl secrets cycle` to correct that.")
	}

	// Execute fn now that the context has been switched.
	if err = fn(); err != nil {
		// Before returning with an error, return the context back to where it was.
		if mustSwitchK8SContextBack {
			if _, _, switchErr := switchK8SContext(oldK8SContext, true); switchErr != nil {
				printError("Failed to reset the kubernetes context:", switchErr)
			}
		}

		return err
	}

	// Switch the context back, error out if there was a problem switching.
	if mustSwitchK8SContextBack {
{'fraction_non_alphanumeric': 0.1109882005899705, 'fraction_numerical': 0.014257620452310717, 'mean_word_length': 3.741841491841492, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2719138', 'n_tokens_mistral': 2888, 'n_tokens_neox': 2760, 'n_words': 834}