diff --git a/Dockerfile b/Dockerfile index becaa45..2b131c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ FROM alpine:latest -RUN apk --no-cache add openssh-client jq \ +RUN apk --no-cache add bash openssh-client jq \ && adduser --no-create-home --uid 1000 -D user \ && mkdir -p /opt/resource/ USER 1000:1000 -WORKDIR /tmp/ -COPY check in out /opt/resource/ +WORKDIR /opt/resource/ +COPY common check in out /opt/resource/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..57a1150 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# concourse-ssh-resource + +A resource type for a ssh resource + +## Source configuration + +``` + + +``` + +- hostname: *Required*. Servers hostname to connect to. +- port: *Optional*. *Default* `22`. Port the ssh server accepts connections on. +- user: *Required*. User as which to connect. +- identity: *Required*. The private key used to authenticate. +- hostkey: *Required*. The hostkey of the server. +- files: *Optional*. File paths on the remote to get/put diff --git a/check b/check index 0617957..6369a3e 100755 --- a/check +++ b/check @@ -1 +1,53 @@ #!/usr/bin/env sh + +set -e + +. ./common + +fetch_file_infos() { + files_file="$(mktemp -tp /tmp)" +ssh -F "$CONFIG_PATH" "$HOSTNAME" sh -s << EOF > "$files_file" + files="$(get_files)" + echo "\$files" | while read -r file; do + echo "\$file" + [ -e "\$file" ] && echo true || echo false + [ -e "\$file" ] && echo "\$(stat --format=%Y "\$file")" || echo + done +EOF + echo "$files_file" + return 0 +} + +_compute_version() { + echo "[" + last_line= + line_file= + line_exists= + line_modify= + while read -r line; do + if [ -z "$line_file" ]; then + line_file="$line" + elif [ -z "$line_exists" ]; then + line_exists="$line" + elif [ -z "$line_modify" ]; then + line_modify="$line" + else + if "$line_exists"; then + echo '{"path":' "\"$line_file\"," '"modify":' "$line_modify" '}', + fi + line_file="$line" + line_exists= + line_modify= + fi + done < "$1" + if [ -n "$line_file" ] && [ -n "$line_exists" ] && [ -n "$line_modify" ] && "$line_exists"; then + echo '{"path":' "\"$line_file\"," '"modify":' "$line_modify" '}' + fi + echo "]" +} + +compute_version() { + _compute_version "$@" | jq -r tostring +} + +compute_version "$(fetch_file_infos)" diff --git a/common b/common new file mode 100755 index 0000000..0894a77 --- /dev/null +++ b/common @@ -0,0 +1,61 @@ +#!/usr/bin/env sh + +INPUT_PATH= +CONFIG_PATH= +HOSTNAME= +PORT= +USER= +IDENTITY= +HOSTKEY= + +save_input() { + input_file="$(mktemp -tp /tmp)" + cat > "$input_file" <&0 + echo "$input_file" + return 0 +} + +read_config() { + HOSTNAME="$(jq -r .source.hostname < "$1")" + PORT="$(jq -r '.source.port // "22"' < "$1")" + USER="$(jq -r .source.user < "$1")" + IDENTITY="$(jq -r .source.identity < "$1")" + HOSTKEY="$(jq -r .source.hostkey < "$1")" + return 0 +} + +write_config() { + directory="$(mktemp -dp /tmp)" + config="$directory/config" + identity_file="$directory/identity" + knownhosts_file="$directory/knownhosts" + + { + echo "host $HOSTNAME" + echo " HostName $HOSTNAME" + echo " Port $PORT" + echo " User $USER" + echo " IdentityFile $identity_file" + echo " UserKnownHostsFile $knownhosts_file" + } > "$config" + echo "$IDENTITY" > "$identity_file" + echo "$HOSTKEY" > "$knownhosts_file" + chmod 600 "$identity_file" "$knownhosts_file" "$config" + echo "$config" + return 0 +} + +INPUT_PATH="$(save_input)" +read_config "$INPUT_PATH" +CONFIG_PATH="$(write_config)" + +export INPUT_PATH +export CONFIG_PATH + +get_version() { + jq -r '.version // []' < "$INPUT_PATH" +} + +get_files() { + jq -r '.source.files?[]' < "$INPUT_PATH" +} diff --git a/in b/in index 0617957..6842d56 100755 --- a/in +++ b/in @@ -1 +1,39 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash + +set -e +set -o pipefail + +. ./common + +cd "$1" +ssh -F "$CONFIG_PATH" "$HOSTNAME" sh -s << EOF | tar x + files="$(get_version | jq -r .[].path)" + archive="\$(mktemp -t)" + files_path="\$(mktemp -t)" + head --bytes=10240 /dev/zero > "\$archive" + echo "\$files" > "\$files_path" + error=false + while read -r filepath; do + if [ ! -e "\$filepath" ]; then + echo "File not found on remote: \$filepath" >&2 + error=true + break + fi + tar rf "\$archive" "\$filepath" + done < "\$files_path" + if ! "\$error"; then + cat "\$archive" + fi + rm "\$archive" + if "\$error"; then + exit 1 + else: + exit 0 + fi +EOF + +jq -r tostring << EOF +{ + "version": $(get_version) +} +EOF