Aashish Jolly
Aashish Jolly

Reputation: 71

Multi-line bash script in yaml for EC2 Image Builder

I'm trying to create a custom component document. While I've tested the yaml file using various yaml linters, EC2 Image builder is complaining with the below error

Failed to create component. Fix the error(s) and try again:
The value supplied for parameter 'data' is not valid. Parsing step 'ConfigureMySQL' in phase 'build' failed. Error: line 4: cannot unmarshal map into string.

And I'm unable to figure out what is wrong with my yaml file

name: MyJavaAppTestDocument
description: This is JavaApp Document
schemaVersion: 1.0

phases:
  - name: build
    steps:
      - name: InstallSoftware
        action: ExecuteBash
        inputs:
          commands:
            - sudo yum update -y
            - sudo yum install -y java-1.8.0
            - sudo amazon-linux-extras install -y tomcat8.5
            - sudo yum install -y https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
            - sudo yum install -y mysql-community-server
      
      - name: ConfigureTomcat
        action: ExecuteBash
        inputs:
          commands:
            - sudo sed -i 's/<\/tomcat-users>/\n<role rolename="manager-gui"\/>\n  <role 
              rolename="manager-script"\/>\n  <role rolename="admin-gui"\/>\n  <user username="admin" 
              password="admin" roles="manager-gui,manager-script,admin-gui"\/>\n<\/tomcat-users>/' 
              /etc/tomcat/tomcat-users.xml
            - sudo systemctl start tomcat
            - sudo systemctl enable tomcat
      
      - name: ConfigureMySQL
        action: ExecuteBash
        inputs:
          commands:
            - sudo systemctl start mysqld
            - sudo systemctl enable mysqld
            - mysqlpass=$(sudo grep 'temporary password' /var/log/mysqld.log | sed 's/.*root@localhost: //')
            - mysql -u root -p$mysqlpass --connect-expired-password -h localhost -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'whyDoTh1s@2020'"
            - |
              sudo cat <<EoF > /tmp/mysql-create-user.sql
              CREATE USER 'admin'@'%' IDENTIFIED BY 'whyDoTh1s@2020';
              GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION;
              EoF

            - sudo mysql -u root -pwhyDoTh1s@2020 -h localhost < /tmp/mysql-create-user.sql

Appreciate if someone could help me find the error. The objective is to build an AMI with pre-configured software and settings.

Upvotes: 6

Views: 4959

Answers (2)

SRJ
SRJ

Reputation: 2806

Although @micah-l-c answer can help in OP's case.

I would suggest an alternate approach which can also help and can be more correct solution towards this problem.

Erroneous line here is

- mysqlpass=$(sudo grep 'temporary password' /var/log/mysqld.log | sed 's/.*root@localhost: //')

This can be rewritten as

- |-
    mysqlpass=$(sudo grep 'temporary password' /var/log/mysqld.log | sed 's/.*root@localhost: //')

OR

- >-
    mysqlpass=$(sudo grep 'temporary password' /var/log/mysqld.log | sed 's/.*root@localhost: //')

Now : will be escaped fine with above approach.

I faced a similar issue and I will give an example where @micah-l-c solution didn't work and above approach worked fine.

Below was line i was adding in the ec2 image builder component

- echo "user1    ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers

I put single quotes around : and it made /etc/sudoers malformed and thus it didn't work.

I replace above line like this

- |-
    echo "user1    ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers

References :

How to escape indicator characters (i.e. : or - ) in YAML

Upvotes: 4

Micah L-C
Micah L-C

Reputation: 104

You're getting that error because of the : in this line:

- mysqlpass=$(sudo grep 'temporary password' /var/log/mysqld.log | sed 's/.*root@localhost: //')

The YAML parser is interpreting that line as creating a map instead of creating a string entry in an existing map. A workaround I was able to use in my own YAML was to surround the : with single quotes, so the problem line would become

- mysqlpass=$(sudo grep 'temporary password' /var/log/mysqld.log | sed 's/.*root@localhost':' //')

According to my own use and this online YAML parser I tested with that solution applied, that should do the trick.

Upvotes: 1

Related Questions