push
This commit is contained in:
commit
355d82c611
86
DOCS.md
Normal file
86
DOCS.md
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
Use the Rsync plugin to synchronize files to remote hosts, and execute arbitrary commands on those hosts.
|
||||||
|
|
||||||
|
## Config
|
||||||
|
The following parameters are used to configure the plugin:
|
||||||
|
- **user** - user to log in as on the remote machines, defaults to `root`
|
||||||
|
- **key** - private SSH key for the remote machines
|
||||||
|
- **hosts** - hostnames or ip-addresses of the remote machines
|
||||||
|
- **port** - port to connect to on the remote machines, defaults to `22`
|
||||||
|
- **source** - source folder to synchronize from, defaults to `./`
|
||||||
|
- **target** - target folder on remote machines to synchronize to
|
||||||
|
- **include** - rsync include filter
|
||||||
|
- **exclude** - rsync exclude filter
|
||||||
|
- **recursive** - recursively synchronize, defaults to `false`
|
||||||
|
- **delete** - delete target folder contents, defaults to `false`
|
||||||
|
- **args** - instruct plugin to use these additional rsync CLI arguments, example: `"--blocking-io"`
|
||||||
|
- **prescript** - list of commands to execute on remote machines before rsync occurs
|
||||||
|
- **script** - list of commands to execute on remote machines after rsync occurs
|
||||||
|
- **log_level** - ssh log level, defaults to quiet
|
||||||
|
|
||||||
|
It is highly recommended to put your private key into a secret (`rsync_key`) so it is not exposed to users. This can be done using the drone-cli:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
drone secret add \
|
||||||
|
--repository your/repo \
|
||||||
|
--name rsync_key \
|
||||||
|
--data @./id_rsa \
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the secret to your `.drone.yml`:
|
||||||
|
```yaml
|
||||||
|
kind: pipeline
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: rsync
|
||||||
|
image: drillster/drone-rsync
|
||||||
|
settings:
|
||||||
|
user: some-user
|
||||||
|
key:
|
||||||
|
from_secret: rsync_key
|
||||||
|
hosts:
|
||||||
|
- remote1
|
||||||
|
source: ./dist
|
||||||
|
target: ~/packages
|
||||||
|
secrets: [ rsync_key ]
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [secret guides](https://docs.drone.io/user-guide/secrets/pre-repository/) for additional information on secrets.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
```yaml
|
||||||
|
kind: pipeline
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: rsync
|
||||||
|
image: drillster/drone-rsync
|
||||||
|
settings:
|
||||||
|
hosts:
|
||||||
|
- remote1
|
||||||
|
- remote2
|
||||||
|
user:
|
||||||
|
from_secret: rsync_user
|
||||||
|
key:
|
||||||
|
from_secret: rsync_key
|
||||||
|
source: ./dist
|
||||||
|
target: ~/packages
|
||||||
|
include:
|
||||||
|
- "app.tar.gz"
|
||||||
|
- "app.tar.gz.md5"
|
||||||
|
exclude:
|
||||||
|
- "**.*"
|
||||||
|
prescript:
|
||||||
|
- cd ~/packages
|
||||||
|
- md5sum -c app.tar.gz.md5
|
||||||
|
- tar -xf app.tar.gz -C ~/app
|
||||||
|
script:
|
||||||
|
- cd ~/packages
|
||||||
|
- md5sum -c app.tar.gz.md5
|
||||||
|
- tar -xf app.tar.gz -C ~/app
|
||||||
|
```
|
||||||
|
|
||||||
|
The example above illustrates a situation where an app package (`app.tar.gz`) will be deployed to 2 remote hosts (`remote1` and `remote2`). An md5 checksum will be deployed as well. After deploying, the md5 checksum is used to check the deployed package. If successful the package is extracted.
|
||||||
|
|
||||||
|
## Important
|
||||||
|
The script passed to **script** will be executed on remote machines directly after rsync completes to deploy the files. It will be executed step by step until a command returns a non-zero exit-code. If this happens, the entire plugin will exit and fail the build.
|
||||||
|
|
6
Dockerfile
Normal file
6
Dockerfile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
RUN apk add --no-cache --update ca-certificates bash openssh-client rsync
|
||||||
|
COPY upload.sh /usr/local/
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/upload.sh"]
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Drillster
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
30
README.md
Normal file
30
README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# drone-rsync
|
||||||
|
[](https://hub.docker.com/r/drillster/drone-rsync/)
|
||||||
|
|
||||||
|
This is a pure Bash [Drone](https://github.com/drone/drone) >= 0.5 plugin to sync files to remote hosts.
|
||||||
|
|
||||||
|
For more information on how to use the plugin, please take a look at [the docs](https://github.com/Drillster/drone-rsync/blob/master/DOCS.md).
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
Build the docker image by running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build --rm=true -t drillster/drone-rsync .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Execute from the working directory (assuming you have an SSH server running on 127.0.0.1:22):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm \
|
||||||
|
-e PLUGIN_KEY=$(cat some-private-key) \
|
||||||
|
-e PLUGIN_HOSTS="127.0.0.1, 127.0.0.2, 127.0.0.3" \
|
||||||
|
-e PLUGIN_PORTS="22, 23, 24" \
|
||||||
|
-e PLUGIN_TARGET="./" \
|
||||||
|
-e PLUGIN_PRESCRIPT="echo \"Prescript Done!\"" \
|
||||||
|
-e PLUGIN_SCRIPT="echo \"Postscript Done!\"" \
|
||||||
|
-e PLUGIN_ARGS="--blocking-io" \
|
||||||
|
-v $(pwd):$(pwd) \
|
||||||
|
-w $(pwd) \
|
||||||
|
drillster/drone-rsync
|
||||||
|
```
|
153
upload.sh
Executable file
153
upload.sh
Executable file
@ -0,0 +1,153 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ -z "$PLUGIN_HOSTS" ]; then
|
||||||
|
echo "Specify at least one host!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PLUGIN_TARGET" ]; then
|
||||||
|
echo "Specify a target!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEFAULT_PORT=$PLUGIN_PORT
|
||||||
|
if [ -z "$PLUGIN_PORT" ]; then
|
||||||
|
echo "Port not specified, using default port 22!"
|
||||||
|
DEFAULT_PORT="22"
|
||||||
|
fi
|
||||||
|
|
||||||
|
SOURCE=$PLUGIN_SOURCE
|
||||||
|
if [ -z "$PLUGIN_SOURCE" ]; then
|
||||||
|
echo "No source folder specified, using default './'"
|
||||||
|
SOURCE="./"
|
||||||
|
fi
|
||||||
|
|
||||||
|
USER=$RSYNC_USER
|
||||||
|
if [ -z "$RSYNC_USER" ]; then
|
||||||
|
if [ -z "$PLUGIN_USER" ]; then
|
||||||
|
echo "No user specified, using root!"
|
||||||
|
USER="root"
|
||||||
|
else
|
||||||
|
USER=$PLUGIN_USER
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
SSH_KEY=$RSYNC_KEY
|
||||||
|
if [ -z "$RSYNC_KEY" ]; then
|
||||||
|
if [ -z "$PLUGIN_KEY" ]; then
|
||||||
|
echo "No private key specified!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
SSH_KEY=$PLUGIN_KEY
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PLUGIN_ARGS" ]; then
|
||||||
|
ARGS=
|
||||||
|
else
|
||||||
|
ARGS=$PLUGIN_ARGS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PLUGIN_LOG_LEVEL" ]; then
|
||||||
|
LOG_LEVEL=quiet
|
||||||
|
else
|
||||||
|
LOG_LEVEL=$PLUGIN_LOG_LEVEL
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Building rsync command
|
||||||
|
expr="rsync -az $ARGS"
|
||||||
|
|
||||||
|
if [[ -n "$PLUGIN_RECURSIVE" && "$PLUGIN_RECURSIVE" == "true" ]]; then
|
||||||
|
expr="$expr -r"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$PLUGIN_DELETE" && "$PLUGIN_DELETE" == "true" ]]; then
|
||||||
|
expr="$expr --del"
|
||||||
|
fi
|
||||||
|
|
||||||
|
expr="$expr -e 'ssh -p %s -o UserKnownHostsFile=/dev/null -o LogLevel=$LOG_LEVEL -o StrictHostKeyChecking=no'"
|
||||||
|
|
||||||
|
# Include
|
||||||
|
IFS=','; read -ra INCLUDE <<< "$PLUGIN_INCLUDE"
|
||||||
|
for include in "${INCLUDE[@]}"; do
|
||||||
|
expr="$expr --include=$include"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Exclude
|
||||||
|
IFS=','; read -ra EXCLUDE <<< "$PLUGIN_EXCLUDE"
|
||||||
|
for exclude in "${EXCLUDE[@]}"; do
|
||||||
|
expr="$expr --exclude=$exclude"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Filter
|
||||||
|
IFS=','; read -ra FILTER <<< "$PLUGIN_FILTER"
|
||||||
|
for filter in "${FILTER[@]}"; do
|
||||||
|
expr="$expr --filter=$filter"
|
||||||
|
done
|
||||||
|
|
||||||
|
expr="$expr $SOURCE"
|
||||||
|
|
||||||
|
# Prepare SSH
|
||||||
|
home="/root"
|
||||||
|
|
||||||
|
mkdir -p "$home/.ssh"
|
||||||
|
|
||||||
|
printf "StrictHostKeyChecking no\n" > "$home/.ssh/config"
|
||||||
|
chmod 0700 "$home/.ssh/config"
|
||||||
|
|
||||||
|
keyfile="$home/.ssh/id_rsa"
|
||||||
|
echo "$SSH_KEY" | grep -q "ssh-ed25519"
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
printf "Using ed25519 based key\n"
|
||||||
|
keyfile="$home/.ssh/id_ed25519"
|
||||||
|
fi
|
||||||
|
echo "$SSH_KEY" | grep -q "ecdsa-"
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
printf "Using ecdsa based key\n"
|
||||||
|
keyfile="$home/.ssh/id_ecdsa"
|
||||||
|
fi
|
||||||
|
echo "$SSH_KEY" > $keyfile
|
||||||
|
chmod 0600 $keyfile
|
||||||
|
|
||||||
|
function join_with { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
|
||||||
|
|
||||||
|
# Parse SSH precommands
|
||||||
|
IFS=','; read -ra COMMANDS <<< "$PLUGIN_PRESCRIPT"
|
||||||
|
prescript=$(join_with ' && ' "${COMMANDS[@]}")
|
||||||
|
# Parse SSH postcommands
|
||||||
|
IFS=','; read -ra COMMANDS <<< "$PLUGIN_SCRIPT"
|
||||||
|
postscript=$(join_with ' && ' "${COMMANDS[@]}")
|
||||||
|
|
||||||
|
# Run rsync
|
||||||
|
IFS=','; read -ra HOSTS <<< "$PLUGIN_HOSTS"
|
||||||
|
IFS=','; read -ra PORTS <<< "$PLUGIN_PORTS"
|
||||||
|
result=0
|
||||||
|
for ((i=0; i < ${#HOSTS[@]}; i++))
|
||||||
|
do
|
||||||
|
HOST=${HOSTS[$i]}
|
||||||
|
PORT=${PORTS[$i]}
|
||||||
|
if [ -z $PORT ]
|
||||||
|
then
|
||||||
|
# Default Port 22
|
||||||
|
PORT=$DEFAULT_PORT
|
||||||
|
fi
|
||||||
|
echo $(printf "%s" "$ $(printf "$expr" "$PORT") $USER@$HOST:$PLUGIN_TARGET ...")
|
||||||
|
if [ -n "$PLUGIN_PRESCRIPT" ]; then
|
||||||
|
echo $(printf "%s" "$ ssh -p $PORT $USER@$HOST ...")
|
||||||
|
echo $(printf "%s" " > $prescript ...")
|
||||||
|
eval "ssh -p $PORT $USER@$HOST '$prescript'"
|
||||||
|
result=$(($result+$?))
|
||||||
|
echo $(printf "%s" "$ ssh -p $PORT $USER@$HOST result: $?")
|
||||||
|
if [ "$result" -gt "0" ]; then exit $result; fi
|
||||||
|
fi
|
||||||
|
eval "$(printf "$expr" "$PORT") $USER@$HOST:$PLUGIN_TARGET"
|
||||||
|
result=$(($result+$?))
|
||||||
|
if [ "$result" -gt "0" ]; then exit $result; fi
|
||||||
|
if [ -n "$PLUGIN_SCRIPT" ]; then
|
||||||
|
echo $(printf "%s" "$ ssh -p $PORT $USER@$HOST ...")
|
||||||
|
echo $(printf "%s" " > $postscript ...")
|
||||||
|
eval "ssh -p $PORT $USER@$HOST '$postscript'"
|
||||||
|
result=$(($result+$?))
|
||||||
|
echo $(printf "%s" "$ ssh -p $PORT $USER@$HOST result: $?")
|
||||||
|
if [ "$result" -gt "0" ]; then exit $result; fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit $result
|
Loading…
x
Reference in New Issue
Block a user