Open ghost opened 1 year ago
Redacted screenshot of input config:
Hey @jonbackhaus-mt, if you are comfortable sharing here could you send the file at ~/Library/Caches/fig/scripts/{namespace}.{script-name}.json
where {namespace}
is the team username or the username of you have it under, and {script-name}
is just the name.
Also tried recreating the script and it seems to template correctly for me:
I think I see the issue in the tree
:
{
"uuid": "a5f9d77c-81a6-46d9-bcd1-47b5c35de4a0",
"name": "ssm-tunnel",
"displayName": null,
"description": null,
"templateVersion": 4,
"tags": [],
"rules": [],
"steps": [
{
"name": null,
"parameters": [
{
"name": "aws-profile",
"displayName": null,
"description": "Description...",
"dependsOn": [],
"required": null,
"type": "selector",
"typeData": {
"placeholder": null,
"suggestions": null,
"generators": [
{
"type": "script",
"script": "aws configure list-profiles",
"tree": [
"aws configure list-profiles"
]
}
],
"allowRawTextInput": null,
"multi": null
},
"cli": {
"short": null,
"long": "aws-profile",
"required": true,
"require_equals": false,
"type": {
"String": {
"default": null
}
},
"raw": false
}
},
{
"name": "instance-name",
"displayName": null,
"description": null,
"dependsOn": [],
"required": null,
"type": "selector",
"typeData": {
"placeholder": null,
"suggestions": null,
"generators": [
{
"type": "script",
"script": "aws --profile {{aws-profile}} ec2 describe-instances | jq '.Reservations[] | .Instances[] | select(.State.Name == \"running\") | ( .Tags | map( { (.Key): .Value } ) | add | .Name)' | tr -d '\"' | sort",
"tree": [
"aws --profile ",
{
"name": "aws-profile"
},
" ec2 describe-instances | jq '.Reservations[] | .Instances[] | select(.State.Name == \"running\") | ( .Tags | map( { (.Key): .Value } ) | add | .Name)' | tr -d '\"' | sort"
]
}
],
"allowRawTextInput": null,
"multi": null
},
"cli": {
"short": null,
"long": "instance-name",
"required": true,
"require_equals": false,
"type": {
"String": {
"default": null
}
},
"raw": false
}
},
{
"name": "ssh-private-keyname",
"displayName": null,
"description": null,
"dependsOn": [],
"required": null,
"type": "selector",
"typeData": {
"placeholder": null,
"suggestions": null,
"generators": [
{
"type": "script",
"script": "ls ~/.ssh/",
"tree": [
"ls ~/.ssh/"
]
}
],
"allowRawTextInput": null,
"multi": null
},
"cli": {
"short": null,
"long": "ssh-private-keyname",
"required": true,
"require_equals": false,
"type": {
"String": {
"default": null
}
},
"raw": false
}
},
{
"name": "local-port",
"displayName": null,
"description": null,
"dependsOn": [],
"required": null,
"type": "text",
"typeData": {
"placeholder": "Enter value here"
},
"cli": {
"short": null,
"long": "local-port",
"required": true,
"require_equals": false,
"type": {
"String": {
"default": null
}
},
"raw": false
}
},
{
"name": "remote-host",
"displayName": null,
"description": null,
"dependsOn": [],
"required": null,
"type": "text",
"typeData": {
"placeholder": "Enter value here"
},
"cli": {
"short": null,
"long": "remote-host",
"required": true,
"require_equals": false,
"type": {
"String": {
"default": "localhost"
}
},
"raw": false
}
},
{
"name": "remote-port",
"displayName": null,
"description": null,
"dependsOn": [],
"required": null,
"type": "text",
"typeData": {
"placeholder": "Enter value here"
},
"cli": {
"short": null,
"long": "remote-port",
"required": true,
"require_equals": false,
"type": {
"String": {
"default": null
}
},
"raw": false
}
}
]
},
{
"name": null,
"runtime": "BASH",
"tree": [
"# set AWS_PROFILE globally for this subroutine\nexport AWS_PROFILE=",
{
"name": "aws-profile"
},
"\n\n# use the instance name to query EC2 for matching instance ids (should return one)\nexport INSTANCE_ID=$(aws ec2 describe-instances --filters 'Name=tag:Name,Values=",
{
"name": "instance-name"
},
"' --query 'Reservations[*].Instances[*].InstanceId' --output text)\n\n# derive the SSH public key from the selected SSH private key\nexport SSH_PUBLIC_KEY=$(ssh-keygen -y -f ~/.ssh/",
{
"name": "ssh-private-keyname"
},
")\n\n# add the public SSH key to EC2\n# note: key is ephemeral and will be removed after 60 seconds\naws ec2-instance-connect send-ssh-public-key --instance-id ${INSTANCE_ID} --instance-os-user ec2-user --ssh-public-key \"${SSH_PUBLIC_KEY}\" > /dev/null\n\n# open the SSH tunnel without launching a terminal\nssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -o 'ProxyCommand aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p' -M -S ~/.ssh/ssh-tunnel-ctrl-socket -fnNT -L {{local-port}}:",
{
"name": "remote-host"
},
":",
{
"name": "remote-port"
},
" -i ~/.ssh/",
{
"name": "ssh-private-keyname"
},
" ec2-user@${INSTANCE_ID}\n\n# print results\necho \"SSH Tunnel Established!\"\necho \"localhost:{{local-port}} --> ",
{
"name": "instance-name"
},
" --> ",
{
"name": "remote-host"
},
":",
{
"name": "remote-port"
},
"\"\necho \"\"\nread -p \"Press enter to close the tunnel\"\n\n# close the tunnel\nssh -S ~/.ssh/ssh-tunnel-ctrl-socket -O exit ec2-user@${INSTANCE_ID}"
]
}
],
"namespace": "ise-dee",
"isOwnedByUser": false,
"lastInvokedAt": "2023-02-24T20:31:50.952Z",
"lastInvokedAtByUser": "2023-02-24T20:31:50.952Z",
"invocationTrackStderr": false,
"invocationTrackStdout": false,
"invocationTrackInputs": false,
"invocationDisableTrack": false,
"shouldCache": true
}
I am quite confused by this one!
I added the script specifically to our unit tests and everything is fine, manually recreated the script and it works fine, the cache file looks 100% correct besides the 2 instances where only {{local-port}}
isn't templated.
@grant0417 When/how do you re-generate the template? Given your results, the only thing that is likely different is how we originally wrote the script. (I know I refactored my code a bunch as I tested each step.) Maybe it's a caching issue?
I modified the JSON tree manually and the script now works. (And Fig didn't change anything on the UI side as a result of my updates.) So that's maybe another data point.
UPDATE: I modified the script and ran into the same templating issue again (even after manually correcting the JSON). So it's repeatable, at least within my instance of the script.
Have you tried making a new Fig Script and copying the text to it? Really struggling to figure out what is going on here!
Okay. It just happened again in a brand new script -- no relation to the original script.
Here's the bash source:
# the directory of the script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# the temp directory used, within $DIR
TEMP_PATH=$(mktemp -d)
# check if tmp dir was created
if [[ ! "$TEMP_PATH" || ! -d "$TEMP_PATH" ]]; then
echo "Could not create temp dir"
exit 1
fi
# deletes the temp directory
function cleanup {
rm -rf "$TEMP_PATH"
echo "Deleted temp working directory $TEMP_PATH"
}
# register the cleanup function to be called on the EXIT signal
trap cleanup EXIT
# extract path parts
export RDZIP_FILENAME=$(basename "{{rdzip-filepath}}")
export RDZIP_DIRPATH=$(dirname "{{rdzip-filepath}}")
export RDZIP_DIRNAME=$(basename "${RDZIP_DIRPATH}")
export RDZIP_VERSION=${RDZIP_DIRNAME}
# extract
cp {{rdzip-filepath}} "${TEMP_PATH}/"
unzip "${TEMP_PATH}/${RDZIP_FILENAME}" -d "${TEMP_PATH}"
# end
read -p "Press enter to terminate script."
JSON attached: ise-dee.rdzip-unpacker.json.zip
The cp {{rdzip-filepath}} "${TEMP_PATH}/"
line does not properly template/render in the JSON, which causes the Fig variable to be incorrectly exposed in the Bash call.
FYI -- this is still happening. I'm trying to debug another script. I'm watching the json
file from ~/Library/Caches/fig/scripts
in the background and can see Fig not properly unpacking a variable in the script tree.
Is there anything else I can do to help debug/resolve this issue?
@mschrage any ideas what to do here, I tried to debug this pretty deeply back when it was reported but could not figure out what was going on.
@mschrage -- I've got this happening across multiple scripts, all within our organization. I've tried everything I can think of to fix it without some kind of nuclear option (like start a new organization). This bug is already blocking some of our more advanced workflows -- like using AWS SSM to open an SSH tunnel. We're open to continuing the debugging conversation if you all can support the activity.
Checks
fig doctor
in the affected terminal sessionfig restart
and replicated the issue againOperating system
macOS 13.2.1 (22D68)
Expected behaviour
The script is based on this blog post, which provides an example for how to use AWS SSM to connect to a remote EC2 instance through the CLI: SSM Session Manager - no bastion host necessary!. We already use Fig for this successfully, so I wanted to extend our scripts to cover SSH tunnels.
Our script takes a bunch of user inputs, does a few AWS CLI lookups, and then fills in all the information necessary to open an SSH tunnel to a remote host. The Fig script should take all these inputs and interpolate a well-formed SSH statement to open a remote tunnel.
Actual behaviour
Fig doesn't properly interpolate one of our variables, resulting in a malformed SSH statement.
Things we've tried:
Steps to reproduce
Script inputs:
aws-profile
: a string (name) of the AWS profile, computed fromaws configure list-profiles
instance-name
: a string (name) of an AWS EC2 instancessh-private-keyname
: a string (filename) of an SSH keyfile (NOTE: file picker wasn't cooperating with my~/.ssh/
directory, so I elected to do a brute-forcels ~/.ssh/
generator)local-port
: a string (integer) port numberremote-host
: a string (hostname) of the remote hostremote-port
: a string (integer) port numberScript code (Bash):
Which returns:
Bad local forwarding specification '{{local-port}}:localhost:1085'
Environment