argoproj / argo-workflows

Workflow Engine for Kubernetes
https://argo-workflows.readthedocs.io/
Apache License 2.0
14.83k stars 3.17k forks source link

Ill-formed scp-like `git clone` URLs lead to unintuitive error message #12152

Open sigwinch28 opened 10 months ago

sigwinch28 commented 10 months ago

Pre-requisites

What happened/what you expected to happen?

When I use a repo of the form user@host/repo instead of user@host:repo for git input artifacts (i.e., I accidentally use an incorrect forward slash instead of the correct colon), the pipeline fails with an unintuitive error message of exec: \"git\": executable file not found in $PATH

Here is how I reproduced it:

$ argo submit -n argo-workflows repro.yaml --wait
Name:                repro-lnkfl
Namespace:           argo-workflows
ServiceAccount:      unset (will run with the default ServiceAccount)
Status:              Pending
Created:             Sun Nov 05 14:25:19 +0000 (now)
Progress:
repro-lnkfl Failed at 2023-11-05 14:25:29 +0000 GMT

$ argo logs -n argo-workflows repro-lnkfl -c init
repro-lnkfl: time="2023-11-05T14:25:20.472Z" level=info msg="Starting Workflow Executor" version=v3.5.1
repro-lnkfl: time="2023-11-05T14:25:20.477Z" level=info msg="Using executor retry strategy" Duration=1s Factor=1.6 Jitter=0.5 Steps=5
repro-lnkfl: time="2023-11-05T14:25:20.477Z" level=info msg="Executor initialized" deadline="0001-01-01 00:00:00 +0000 UTC" includeScriptOutput=false namespace=argo-workflows podName=repro-lnkfl template="{\"name\":\"git-clone\",\"inputs\":{\"artifacts\":[{\"name\":\"argo-source\",\"path\":\"/src\",\"git\":{\"repo\":\"git@github.com/argoproj/argo-workflows.git\",\"revision\":\"v3.5.1\",\"sshPrivateKeySecret\":{\"name\":\"github-credentials\",\"key\":\"ssh-private-key\"}}}]},\"outputs\":{},\"metadata\":{},\"container\":{\"name\":\"\",\"image\":\"golang:1.10\",\"command\":[\"sh\",\"-c\"],\"args\":[\"git status \\u0026\\u0026 ls\"],\"workingDir\":\"/src\",\"resources\":{}}}" version="&Version{Version:v3.5.1,BuildDate:2023-11-03T18:37:58Z,GitCommit:877c5523066e17687856fe3484c9b2d398e986f5,GitTag:v3.5.1,GitTreeState:clean,GoVersion:go1.21.3,Compiler:gc,Platform:linux/amd64,}"
repro-lnkfl: time="2023-11-05T14:25:20.604Z" level=info msg="Start loading input artifacts..."
repro-lnkfl: time="2023-11-05T14:25:20.604Z" level=info msg="Downloading artifact: argo-source"
repro-lnkfl: time="2023-11-05T14:25:20.605Z" level=info msg="Load artifact" artifactName=argo-source duration=1.234711ms error="failed to clone \"git@github.com/argoproj/argo-workflows.git\": exec: \"git\": executable file not found in $PATH" key=
repro-lnkfl: time="2023-11-05T14:25:20.605Z" level=error msg="executor error: artifact argo-source failed to load: failed to clone \"git@github.com/argoproj/argo-workflows.git\": exec: \"git\": executable file not found in $PATH"
repro-lnkfl: time="2023-11-05T14:25:20.605Z" level=info msg="Alloc=9280 TotalAlloc=13289 Sys=25189 NumGC=3 Goroutines=4"
repro-lnkfl: time="2023-11-05T14:25:20.605Z" level=fatal msg="artifact argo-source failed to load: failed to clone \"git@github.com/argoproj/argo-workflows.git\": exec: \"git\": executable file not found in $PATH"

Version

v3.5.1

Paste a small workflow that reproduces the issue. We must be able to run the workflow; don't enter a workflows that uses private images.

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: repro-
spec:
  entrypoint: git-clone
  templates:
    - name: git-clone
      inputs:
        artifacts:
          - name: argo-source
            path: /src
            git:
              repo: git@github.com/argoproj/argo-workflows.git # note the incorrect use of a / instead of a : for this clone
              revision: "v3.5.1"
              sshPrivateKeySecret:
                name: github-credentials
                key: ssh-private-key
      container:
        image: golang:1.10
        command: [sh, -c]
        args: ["git status && ls"]
        workingDir: /src

Logs from the workflow controller

time="2023-11-05T14:25:19.701Z" level=info msg="Processing workflow" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:19.706Z" level=info msg="Updated phase  -> Running" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:19.706Z" level=warning msg="Node was nil, will be initialized as type Skipped" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:19.706Z" level=info msg="was unable to obtain node for , letting display name to be nodeName" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:19.706Z" level=info msg="Pod node repro-lnkfl initialized Pending" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:19.721Z" level=info msg="Created pod: repro-lnkfl (repro-lnkfl)" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:19.721Z" level=info msg="TaskSet Reconciliation" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:19.721Z" level=info msg=reconcileAgentPod namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:19.732Z" level=info msg="Workflow update successful" namespace=argo-workflows phase=Running resourceVersion=858422 workflow=repro-lnkfl
time="2023-11-05T14:25:29.725Z" level=info msg="Processing workflow" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:29.725Z" level=info msg="Task-result reconciliation" namespace=argo-workflows numObjs=0 workflow=repro-lnkfl
time="2023-11-05T14:25:29.725Z" level=info msg="Pod failed: Error (exit code 1): artifact argo-source failed to load: failed to clone \"git@github.com/argoproj/argo-workflows.git\": exec: \"git\": executable file not found in $PATH" displayName=repro-lnkfl namespace=argo-workflows pod=repro-lnkfl templateName=git-clone workflow=repro-lnkfl
time="2023-11-05T14:25:29.725Z" level=info msg="marking node as failed since init container has non-zero exit code" namespace=argo-workflows new.phase=Failed workflow=repro-lnkfl
time="2023-11-05T14:25:29.725Z" level=info msg="node changed" namespace=argo-workflows new.message="Error (exit code 1): artifact argo-source failed to load: failed to clone \"git@github.com/argoproj/argo-workflows.git\": exec: \"git\": executable file not found in $PATH" new.phase=Failed new.progress=0/1 nodeID=repro-lnkfl old.message= old.phase=Pending old.progress=0/1 workflow=repro-lnkfl
time="2023-11-05T14:25:29.726Z" level=info msg="TaskSet Reconciliation" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:29.726Z" level=info msg=reconcileAgentPod namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:29.726Z" level=info msg="Updated phase Running -> Failed" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:29.726Z" level=info msg="Updated message  -> Error (exit code 1): artifact argo-source failed to load: failed to clone \"git@github.com/argoproj/argo-workflows.git\": exec: \"git\": executable file not found in $PATH" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:29.726Z" level=info msg="Marking workflow completed" namespace=argo-workflows workflow=repro-lnkfl
time="2023-11-05T14:25:29.731Z" level=info msg="cleaning up pod" action=deletePod key=argo-workflows/repro-lnkfl-1340600742-agent/deletePod
time="2023-11-05T14:25:29.737Z" level=info msg="Workflow update successful" namespace=argo-workflows phase=Failed resourceVersion=858437 workflow=repro-lnkfl
time="2023-11-05T14:25:29.749Z" level=info msg="cleaning up pod" action=labelPodCompleted key=argo-workflows/repro-lnkfl/labelPodCompleted

Logs from in your workflow's wait container

Error from server (BadRequest): container "wait" in pod "repro-lnkfl" is waiting to start: PodInitializing
sigwinch28 commented 10 months ago

I speculate that my malformed scp-style URLs are being intepreted as file:// URLs, which are unsupported by go-git:

https://github.com/go-git/go-git/blob/master/COMPATIBILITY.md#transport-schemes

sigwinch28 commented 10 months ago

I speculate that my malformed scp-style URLs are being intepreted as file:// URLs, which are unsupported by go-git:

https://github.com/go-git/go-git/blob/master/COMPATIBILITY.md#transport-schemes

This appears to be what's happening. Reproduced using the same version of go-git as argo-workflows:

go.mod:

module github.com/sigwinch28/go-git-scp-repro

go 1.21.3

require github.com/go-git/go-git/v5 v5.4.2

require (
    github.com/acomagu/bufpipe v1.0.3 // indirect
    github.com/go-git/gcfg v1.5.0 // indirect
    github.com/go-git/go-billy/v5 v5.3.1 // indirect
    github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
    github.com/mitchellh/go-homedir v1.1.0 // indirect
    golang.org/x/net v0.0.0-20210326060303-6b1517762897 // indirect
    golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79 // indirect
    gopkg.in/warnings.v0 v0.1.2 // indirect
)

main.go:

package main

import (
    "fmt"

    "github.com/go-git/go-git/v5/plumbing/transport"
)

func main() {
    wellFormed, err := transport.NewEndpoint("git@github.com:argo/argo-workflows.git")
    if err != nil {
        panic(err)
    }
    fmt.Printf("Well-formed: %s\n", wellFormed.String())

    illFormed, err := transport.NewEndpoint("git@github.com/argo/argo-workflows.git")
    if err != nil {
        panic(err)
    }
    fmt.Printf("Ill-formed: %s\n", illFormed.String())
}

output of go run main.go:

Well-formed: ssh://git@github.com/argo/argo-workflows.git
Ill-formed: file://git@github.com/argo/argo-workflows.git
sigwinch28 commented 10 months ago

A workaround for users wanting file:// support is to add the git executable to their executor image, e.g. using the following Dockerfile:

#syntax=docker/dockerfile:1.4
ARG ARGO_WORKFLOWS_VERSION
FROM quay.io/argoproj/argoexec:v${ARGO_WORKFLOWS_VERSION} as argoexec

FROM alpine:3.18

RUN apk update && apk add --no-cache git

COPY --link --from=argoexec /bin/argoexec /bin/argoexec

Then running docker build --build-arg ARGO_WORKFLOWS_VERSION=<<your version of argo workflows here>> ., publishing the image somewhere, and updating the workflows controller arguments to use your published image.

When I run the workflow posted above using this modified image, I get the expected repository not found error which is less cryptic.

$ argo submit -n argo-workflows --wait repro.yaml
Name:                repro-prnml
Namespace:           argo-workflows
ServiceAccount:      unset (will run with the default ServiceAccount)
Status:              Pending
Created:             Sun Nov 05 15:33:23 +0000 (now)
Progress:
repro-prnml Failed at 2023-11-05 15:33:33 +0000 GMT

$ argo logs -n argo-workflows repro-prnml -c init
repro-prnml: time="2023-11-05T15:33:26.662Z" level=info msg="Starting Workflow Executor" version=v3.5.1
repro-prnml: time="2023-11-05T15:33:26.666Z" level=info msg="Using executor retry strategy" Duration=1s Factor=1.6 Jitter=0.5 Steps=5
repro-prnml: time="2023-11-05T15:33:26.666Z" level=info msg="Executor initialized" deadline="0001-01-01 00:00:00 +0000 UTC" includeScriptOutput=false namespace=argo-workflows podName=repro-prnml template="{\"name\":\"git-clone\",\"inputs\":{\"artifacts\":[{\"name\":\"argo-source\",\"path\":\"/src\",\"git\":{\"repo\":\"git@github.com/argoproj/argo-workflows.git\",\"revision\":\"v3.5.1\",\"sshPrivateKeySecret\":{\"name\":\"github-credentials\",\"key\":\"ssh-private-key\"}}}]},\"outputs\":{},\"metadata\":{},\"container\":{\"name\":\"\",\"image\":\"golang:1.10\",\"command\":[\"sh\",\"-c\"],\"args\":[\"git status \\u0026\\u0026 ls\"],\"workingDir\":\"/src\",\"resources\":{}}}" version="&Version{Version:v3.5.1,BuildDate:2023-11-03T18:37:58Z,GitCommit:877c5523066e17687856fe3484c9b2d398e986f5,GitTag:v3.5.1,GitTreeState:clean,GoVersion:go1.21.3,Compiler:gc,Platform:linux/amd64,}"
repro-prnml: time="2023-11-05T15:33:26.783Z" level=info msg="Start loading input artifacts..."
repro-prnml: time="2023-11-05T15:33:26.783Z" level=info msg="Downloading artifact: argo-source"
repro-prnml: time="2023-11-05T15:33:26.786Z" level=info msg="Load artifact" artifactName=argo-source duration=3.34862ms error="failed to clone \"git@github.com/argoproj/argo-workflows.git\": repository not found" key=
repro-prnml: time="2023-11-05T15:33:26.786Z" level=error msg="executor error: artifact argo-source failed to load: failed to clone \"git@github.com/argoproj/argo-workflows.git\": repository not found"
repro-prnml: time="2023-11-05T15:33:26.787Z" level=info msg="Alloc=8344 TotalAlloc=12376 Sys=25189 NumGC=3 Goroutines=4"
repro-prnml: time="2023-11-05T15:33:26.787Z" level=fatal msg="artifact argo-source failed to load: failed to clone \"git@github.com/argoproj/argo-workflows.git\": repository not found"
sigwinch28 commented 10 months ago

Root cause is #8292 and #7798. It might be more appropriate to make this a regression in support for the file:// scheme for git artifacts

agilgur5 commented 10 months ago

Follow-up to this Slack thread.

We could potentially catch this exact error and give a friendlier error message like "file:// URL detected, an image with the git binary must be used"