├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md └── assets ├── check ├── common.sh ├── in └── out /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:edge 2 | LABEL MAINTAINER="Troy Kinsella " 3 | 4 | COPY assets/* /opt/resource/ 5 | 6 | RUN apk add --no-cache \ 7 | bash \ 8 | ca-certificates \ 9 | curl \ 10 | jq; \ 11 | update-ca-certificates 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2019 Troy Kinsella 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 6 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 7 | persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 10 | Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 13 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 15 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Concourse Fly Resource 2 | ====================== 3 | 4 | A [Concourse](http://concourse.ci/) resource for manipulating `fly`. 5 | 6 | See [Docker Hub](https://cloud.docker.com/repository/docker/troykinsella/concourse-fly-resource) 7 | for tagged image versions available. 8 | 9 | Compatibility matrix: 10 | 11 | | Concourse Version | Resource Image Tag | 12 | | ----------------- | ------------------ | 13 | | `5.x` | `2.x`, `latest` | 14 | | `4.x` | `2.x`, `latest` | 15 | | `3.x` | `1.x` | 16 | | `2.x` and below | NOPE | 17 | 18 | ## Resource Type Configuration 19 | 20 | ```yaml 21 | resource_types: 22 | - name: fly 23 | type: docker-image 24 | source: 25 | repository: troykinsella/concourse-fly-resource 26 | tag: latest 27 | ``` 28 | 29 | ## Source Configuration 30 | 31 | Currently only HTTP basic authentication is supported. 32 | 33 | * `url`: _Optional_. The base URL of the concourse instance to contact. (i.e. https://ci.concourse-ci.org). 34 | Default: The value of the `$ATC_EXTERNAL_URL` [metadata](https://concourse-ci.org/implementing-resource-types.html#resource-metadata) variable. 35 | * `username`: _Required_. The concourse basic auth username. 36 | * `password`: _Required_. The concourse basic auth password. 37 | * `target`: _Optional_. The name of the target concourse instance. Default: "main". 38 | * `team`: _Optional_. The concourse team to login to. Default: The value of the 39 | `$BUILD_TEAM_NAME` [metadata](https://concourse-ci.org/implementing-resource-types.html#resource-metadata) variable. 40 | * `insecure`: _Optional_. Set to `true` to skip TLS verification. 41 | * `debug`: _Optional_. Set to `true` to print commands (such as `fly login` and `fly sync`) for troubleshooting, including credentials. Default: `false`. 42 | * `secure_output`: _Optional_. Set to `false` to show potentially insecure options and echoed fly commands. Default: `true`. 43 | * `multiline_lines`: _Optional_. Set to `true` to interpret `\` as one line (mostly for big options line). 44 | 45 | ### Example 46 | 47 | ```yaml 48 | resources: 49 | - name: fly 50 | type: fly 51 | source: 52 | url: {{concourse_url}} 53 | username: ((concourse_username)) 54 | password: ((concourse_password)) 55 | team: eh-team 56 | ``` 57 | 58 | ## Behaviour 59 | 60 | ### `check`: No-Op 61 | 62 | ### `in`: No-Op 63 | 64 | ### `out`: Execute `fly` Command 65 | 66 | Execute the given `fly` command along with given options. The `fly` client is downloaded from the target 67 | Concourse instance if not already present. If there is a version mismatch between `fly` and Concourse, 68 | a `fly sync` is performed. 69 | When multiple lines are present in the provided options, `fly` is executed separately for each line. 70 | 71 | #### Parameters 72 | 73 | * `options`: _Optional_. The options to pass to `fly`. 74 | * `options_file`: _Optional_. A file containing options to pass to `fly`. 75 | 76 | Parameters are passed through to the `fly` command as follows: 77 | ```sh 78 | fly -t 79 | ``` 80 | 81 | Concourse [metadata](https://concourse-ci.org/implementing-resource-types.html#resource-metadata) 82 | variables are supported in options. 83 | 84 | #### Example 85 | 86 | ```yaml 87 | - name: trigger-something 88 | plan: 89 | - put: fly 90 | params: 91 | options: trigger-job -j some-pipeline/some-job 92 | ``` 93 | 94 | ## License 95 | 96 | MIT © Troy Kinsella 97 | -------------------------------------------------------------------------------- /assets/check: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo [] 3 | -------------------------------------------------------------------------------- /assets/common.sh: -------------------------------------------------------------------------------- 1 | FLY=/usr/local/bin/fly 2 | 3 | fetch_fly() { 4 | local url=$1 5 | local insecure=$2 6 | 7 | local insecure_arg="" 8 | test "$insecure" = "true" && insecure_arg="--insecure" 9 | 10 | if ! [ -x $FLY ]; then 11 | echo "Fetching fly..." 12 | curl -fSsL $insecure_arg "$url/api/v1/cli?arch=amd64&platform=linux" -o "$FLY" 13 | chmod +x "$FLY" 14 | fi 15 | } 16 | 17 | login() { 18 | local url="$1" 19 | local username="$2" 20 | local password="$3" 21 | local team="$4" 22 | local insecure="$5" 23 | local target="$6" 24 | local tried="$7" 25 | 26 | local insecure_arg="" 27 | test "$insecure" = "true" && insecure_arg="--insecure" 28 | 29 | echo "Logging in..." 30 | local out=$($FLY login -t "$target" $insecure_arg -c "$url" -n "$team" "--username=$username" "--password=$password" 2>&1) 31 | 32 | # This sucks 33 | if echo "$out" | grep "fly -t $target sync" > /dev/null; then 34 | test -n "$tried" && return 1 35 | fetch_fly "$url" "$insecure" 36 | login "$url" "$username" "$password" "$team" "$insecure" "$target" yes 37 | fi 38 | } 39 | 40 | init_fly() { 41 | local url="$1" 42 | local username="$2" 43 | local password="$3" 44 | local team="$4" 45 | local insecure="$5" 46 | local target="$6" 47 | 48 | fetch_fly "$url" "$insecure" 49 | login "$url" "$username" "$password" "$team" "$insecure" "$target" 50 | } 51 | -------------------------------------------------------------------------------- /assets/in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo '{"version":{}}' 3 | -------------------------------------------------------------------------------- /assets/out: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | exec 3>&1 # make stdout available as fd 3 for the result 6 | exec 1>&2 # redirect all output to stderr for logging 7 | 8 | . $(dirname $0)/common.sh 9 | cd "$1" 10 | 11 | payload=$(mktemp /tmp/fly-resource-request.XXXXXX) 12 | cat > "$payload" <&0 13 | 14 | url=$(jq -r ".source.url // \"$ATC_EXTERNAL_URL\"" < $payload) 15 | 16 | username=$(jq -r '.source.username // ""' < $payload) 17 | test -z "$username" && { echo "Must supply 'username' source attribute" >&2; exit 1; } 18 | 19 | password=$(jq -r '.source.password // ""' < $payload) 20 | test -z "$password" && { echo "Must supply 'password' source attribute" >&2; exit 1; } 21 | 22 | team=$(jq -r ".source.team // \"$BUILD_TEAM_NAME\"" < $payload) 23 | target=$(jq -r '.source.target // "main"' < $payload) 24 | insecure=$(jq -r '.source.insecure // "false"' < $payload) 25 | debug=$(jq -r '.source.debug // "false"' < $payload) 26 | multiline_lines=$(jq -r '.source.multiline_lines // "false"' < $payload) 27 | secure_output=$(jq -r '.source.secure_output // "true"' < $payload) 28 | 29 | options=$(jq -r '.params.options // ""' < $payload) 30 | options_file=$(jq -r '.params.options_file // ""' < $payload) 31 | 32 | if [ -z "$options" ] && [ -z "$options_file" ]; then 33 | echo "Must supply one of 'options' or 'options_file', not both" >&2 34 | exit 1 35 | fi 36 | if [ -n "$options_file" ]; then 37 | options=$(cat "$options_file") 38 | fi 39 | if [ -z "$options" ]; then 40 | echo "Must supply some options to fly" >&2 41 | exit 1 42 | fi 43 | 44 | expanded_options=$(sed "s/\$BUILD_ID/$BUILD_ID/g" <<<$options) 45 | expanded_options=$(sed "s/\$BUILD_TEAM_NAME/$BUILD_TEAM_NAME/g" <<<$expanded_options) 46 | expanded_options=$(sed "s/\$BUILD_JOB_NAME/$BUILD_JOB_NAME/g" <<<$expanded_options) 47 | expanded_options=$(sed "s/\$BUILD_PIPELINE_NAME/$BUILD_PIPELINE_NAME/g" <<<$expanded_options) 48 | expanded_options=$(sed "s/\$BUILD_NAME/$BUILD_NAME/g" <<<$expanded_options) 49 | expanded_options=$(sed "s@\$ATC_EXTERNAL_URL@$ATC_EXTERNAL_URL@g" <<<$expanded_options) # use another separator to avoid conflit with replaced url 50 | 51 | if [ "$secure_output" = false ]; then 52 | echo "Options: $expanded_options" 53 | else 54 | echo "Options: ##SUPRESSED##" 55 | fi 56 | 57 | test "$debug" = "true" && set -x 58 | 59 | init_fly "$url" "$username" "$password" "$team" "$insecure" "$target" 60 | 61 | READSWITCH="-r" 62 | 63 | if [ "$multiline_lines" = true ]; then 64 | READSWITCH="" 65 | fi 66 | 67 | while read $READSWITCH line; do 68 | ( 69 | if [ "$secure_output" = false ]; then 70 | set -x 71 | fi 72 | fly -t "$target" $line 73 | ) 74 | done <<< "$expanded_options" 75 | 76 | jq -n "{ 77 | version: {} 78 | }" >&3 79 | --------------------------------------------------------------------------------