<p>Building off another one of my questions about <a href="https://stackoverflow.com/questions/60061593/tie-skaffold-profile-to-namespace">tying profiles to namespaces</a>, is there a way to tie profiles to clusters?</p>

<p>I've found a couple times now that I accidentally run commands like <code>skaffold run -p local -n skeleton</code> when my current kubernetes context is pointing to <code>docker-desktop</code>. I'd like to prevent myself and other people on my team from committing the same mistake.</p>

<p>I found that there's a way of <a href="https://skaffold.dev/docs/environment/kube-context/" rel="nofollow noreferrer">specifying contexts</a> but that doesn't play nicely if developers use custom contexts like <code>kubeclt set-context custom --user=custom --cluster=custom</code>. I've also found a <a href="https://skaffold.dev/docs/references/yaml/" rel="nofollow noreferrer">cluster field</a> in the <code>skaffold.yaml</code> reference but it seems that doesn't satisfy my need because it doesn't let me specify a cluster name.</p>

Paymahn Moghadasian
<p>After digging through the <a href="https://skaffold.dev/docs/" rel="nofollow noreferrer">skaffold documentation</a> and performing several tests I finally managed to find at least partial solution of your problem, maybe not the most elegant one, but still functional. If I find a better way I will edit my answer.</p>

<p>Let's start from the beginning:</p>

<p>As we can read <a href="https://skaffold.dev/docs/environment/kube-context/" rel="nofollow noreferrer">here</a>:</p>

<blockquote>
  <p>When interacting with a Kubernetes cluster, just like any other
  Kubernetes-native tool, Skaffold requires a valid Kubernetes context
  to be configured. The selected kube-context determines the Kubernetes
  cluster, the Kubernetes user, and the default namespace. By default,
  Skaffold uses the current kube-context from your kube-config file.</p>
</blockquote>

<p>This is quite important point as we are actually starting from <code>kube-context</code> and based on it we are able to trigger specific profile, never the oposite.</p>

<p><strong>important to remember</strong>: <code>kube-context</code> is not activated based on the <code>profile</code> but the opposite is true: the specific <code>profile</code> is triggered based on the current context (selected by <code>kubectl config use-context</code>).</p>

<p>Although we can overwrite default settings from our <code>skaffold.yaml</code> config file by patching (<a href="https://stackoverflow.com/questions/60061593/tie-skaffold-profile-to-namespace/60107468#60107468">compare related answer</a>), it's not possible to overwrite the <code>current-context</code> based on slected <code>profile</code> e.g. manually as in your command:</p>

<pre><code>skaffold -p prod
</code></pre>

<p>Here you are manually selecting specific <code>profile</code>. This way you bypass automatic <a href="https://skaffold.dev/docs/environment/profiles/" rel="nofollow noreferrer">profile triggering</a>. As the documentation says:</p>

<blockquote>
  <p><strong>Activations in skaffold.yaml</strong>: You can auto-activate a profile based on</p>
  
  <ul>
  <li>kubecontext (could be either a string or a regexp: prefixing with <code>!</code> will negate the match)</li>
  <li>environment variable value</li>
  <li>skaffold command (dev/run/build/deploy)</li>
  </ul>
</blockquote>

<p>Let's say we want to activate our profile based on current <code>kube-context</code> only to make it simple however we can join different conditions together by AND and OR like in the example <a href="https://skaffold.dev/docs/environment/profiles/" rel="nofollow noreferrer">here</a>.</p>

<h3>solution</h3>

<blockquote>
  <p>I want to make sure that if I run skaffold -p prod skaffold will fail
  if my kubecontext points to a cluster other than my production
  cluster.</p>
</blockquote>

<p>I'm affraid it cannot be done this way. If you've already manually selected <code>prod profile</code> by <code>-p prod</code> you're bypassing selection of profile based on current context therefore you already chosen <strong>what can be done</strong> no matter how <strong>where it can be done</strong> is set (currently selected <code>kube-context</code>). <strong>In this situation <code>skaffold</code> doesn't have any mechanisms that would prevent you from running something on wrong cluster</strong>. In other words you're forcing this way certain behaviour of your pipeline. You already agree to it by selecting the profile. If you gave up using <code>-p</code> or <code>--profile</code> flags, certain profiles will never be triggerd unless currently selected <code>kube-context</code> does it automatically. <code>skaffold</code> just won't let that happen.</p>

<p>Let's look at the following example showing how to make it work:</p>

<pre><code>apiVersion: skaffold/v2alpha3
kind: Config
metadata:
  name: getting-started
build:
  artifacts:
  - image: skaffold-example
    docker:
      dockerfile: NonExistingDockerfile # the pipeline will fail at build stage
  cluster:
deploy:
  kubectl:
    manifests:
    - k8s-pod.yaml
    flags:
      global: # additional flags passed on every command.
      - --namespace=default
  kubeContext: minikube
profiles:
- name: prod
  patches:
  - op: replace
    path: /build/artifacts/0/docker/dockerfile
    value: Dockerfile
  - op: replace
    path: /deploy/kubectl/flags/global/0
    value: --namespace=prod
  activation:
  - kubeContext: minikube
    command: run 
  - kubeContext: minikube
    command: dev 
</code></pre>

<p>In general part of our <code>skaffold.yaml</code> config we configured:</p>

<pre><code>dockerfile: NonExistingDockerfile # the pipeline will fail at build stage
</code></pre>

<p>Untill we name our <code>Dockerfile</code> - <code>"NonExistingDockerfile"</code> every pipeline will fail at its <code>build</code> stage. So by default all builds, no matter what <code>kube-context</code> is selected are destined to fail. Hovewer we can override this default behaviour by <code>patching</code> specific fragment of the <code>skaffold.yaml</code> in our <code>profile</code> section and setting again <code>Dockerfile</code> to its standard name. This way every:</p>

<pre><code>skaffold run
</code></pre>

<p>or</p>

<pre><code>skaffold dev
</code></pre>

<p>command will succeed only if the current <code>kube-context</code> is set to <code>minikube</code>. Otherwise it will fail.</p>

<p>We can check it with:</p>

<pre><code>skaffold run --render-only
</code></pre>

<p>previously setting our current <code>kube-context</code> to the one that matches what is present in the <code>activation</code> section of our <code>profile</code> definition.</p>

<blockquote>
  <p>I've found a couple times now that I accidentally run commands like
  <code>skaffold run -p local -n skeleton</code> when my current kubernetes context
  is pointing to <code>docker-desktop</code>. I'd like to prevent myself and other
  people on my team from committing the same mistake.</p>
</blockquote>

<p>I understand your point that it would be nice to have some built-in mechanism that prevents overriding this automatic profile activation configured in <code>skaffold.yaml</code> by command line options, but it looks like currently it isn't possible. If you don't specify <code>-p local</code>, <code>skaffold</code> will always choose the correct profile based on the current <code>context</code>. Well, it looks like good material for <strong>feature request</strong>.</p>
