Reputation: 1723
I have this ECS task definition as follow:
{
...
"image": "123.dkr.ecr.us-east-1.amazonaws.com/foo:1.0",
...
"image": "123.dkr.ecr.us-east-1.amazonaws.com/bar:latest",
....
}
I need to replace only the first "image" value, for instance:
{
...
"image": "123.dkr.ecr.us-east-1.amazonaws.com/foo:2.0",
...
"image": "123.dkr.ecr.us-east-1.amazonaws.com/bar:latest",
....
}
Here's my command sed -e "s/.*foo:.*/\"image\":\"${REPO}:${VERSION}\",/" taskdef.json
Where REPO=123.dkr.ecr.us-east-1.amazonaws.com/foo
and VERSION=2.0
This is the error I got:
sed: -e expression #1, char 70: unknown option to `s'
This happens because the slash /
from REPO
variable.
Upvotes: 1
Views: 248
Reputation: 92854
The right way with json processor called jq (v1.5):
Sample ECS task definition task.json
:
{
"containerDefinitions": [
{
"name": "wordpress",
"links": [
"mysql"
],
"image": "123.dkr.ecr.us-east-1.amazonaws.com/foo:1.0",
"essential": true,
"portMappings": [
{
"containerPort": 80,
"hostPort": 80
}
],
"memory": 500,
"cpu": 10
},
{
"environment": [
{
"name": "MYSQL_ROOT_PASSWORD",
"value": "password"
}
],
"name": "mysql",
"image": "123.dkr.ecr.us-east-1.amazonaws.com/bar:latest",
"cpu": 10,
"memory": 500,
"essential": true
}
],
"family": "hello_world"
}
The job:
jq '.containerDefinitions[0].image = (.containerDefinitions[0].image | sub("1.0$";"2.0"))' task.json
The output:
{
"containerDefinitions": [
{
"name": "wordpress",
"links": [
"mysql"
],
"image": "123.dkr.ecr.us-east-1.amazonaws.com/foo:2.0",
"essential": true,
"portMappings": [
{
"containerPort": 80,
"hostPort": 80
}
],
"memory": 500,
"cpu": 10
},
{
"environment": [
{
"name": "MYSQL_ROOT_PASSWORD",
"value": "password"
}
],
"name": "mysql",
"image": "123.dkr.ecr.us-east-1.amazonaws.com/bar:latest",
"cpu": 10,
"memory": 500,
"essential": true
}
],
"family": "hello_world"
}
Upvotes: 0
Reputation: 203129
To replace the value for the first image would be:
$ awk -v repo="$REPO" -v vers="$VERSION" '
!f && ($1~/"image"/) { f=1; sub(/:.*/,""); $0=$0 ": \"" repo ":" vers "\"," } 1
' file
{
...
"image": "123.dkr.ecr.us-east-1.amazonaws.com/foo:2.0",
...
"image": "123.dkr.ecr.us-east-1.amazonaws.com/bar:latest",
....
}
The above would convert escape sequences to their literal characters (e.g. \t
to a literal tab character) if they appeared in REPO or VERSION. It's a trivial workaround if that's a possible issue (just set them on the command line or export them then access with ENVIRON[]) and it'll work no matter what other characters appear in the strings since it's using literal string functionality.
Upvotes: 0
Reputation: 307
You can use any character as the delimiter for `s' commands in sed, the first character after s
will be the delimiter. For example - #
sed -e "s#foo:.*#\"image\":\"${REPO}:${VERSION}\",#" taskdef.json
Will resolve this particular issue (assuming no #
in $REPO
or $VERSION
) as the /
will no longer break the pattern.
Upvotes: 2