Repository: serverless/serverless (JavaScript)
Date: 2016-10-23 10:32:52+00:00
Task type: Bug Fix

Issue:
passing a number as a cli option errors
# This is a Bug Report
## Description

If I pass a number as a cli option like this:

`sls deploy --account 999123456`

or this:

`sls deploy --account '999123456'`

or this:

`sls deploy --account "999123456"`

I get this error:

```
Trying to populate non string value into a string for
variable ${opt:account}. Please make sure the value
of the property is a string.
```

I use it for string interpolation like this:

`iamRoleARN: arn:aws:iam::${opt:account}:role/lambda_full_access`

Is there a way to pass a number as a string?  Thanks!
## Additional Data
- **_Serverless Framework Version you're using**_: 1.0.2
- **_Operating System**_: OSX 10.11.6
- **_Stack Trace**_:
- **_Provider Error messages**_:



Issue discussion:
For anyone experiencing the same issue, my workaround is to double quote the number in some way.  eg. `sls deploy --account "'999123456'"`

thanks for reporting. Yup this looks like we should allow strings or numbers to populate into a place where a string can be accepted.


Solution patch:
diff --git a/lib/classes/Variables.js b/lib/classes/Variables.js
index 0ff2b4b82b6..22ff36e3c61 100644
--- a/lib/classes/Variables.js
+++ b/lib/classes/Variables.js
@@ -75,18 +75,22 @@ class Variables {
 
   populateVariable(propertyParam, matchedString, valueToPopulate) {
     let property = propertyParam;
-
     if (typeof valueToPopulate === 'string') {
       property = replaceall(matchedString, valueToPopulate, property);
     } else {
       if (property !== matchedString) {
-        const errorMessage = [
-          'Trying to populate non string value into',
-          ` a string for variable ${matchedString}.`,
-          ' Please make sure the value of the property is a string.',
-        ].join('');
-        throw new this.serverless.classes
-          .Error(errorMessage);
+        if (typeof valueToPopulate === 'number') {
+          property = replaceall(matchedString, String(valueToPopulate), property);
+        } else {
+          const errorMessage = [
+            'Trying to populate non string value into',
+            ` a string for variable ${matchedString}.`,
+            ' Please make sure the value of the property is a string.',
+          ].join('');
+          throw new this.serverless.classes
+            .Error(errorMessage);
+        }
+        return property;
       }
       property = valueToPopulate;
     }


Test patch:
diff --git a/lib/classes/Variables.test.js b/lib/classes/Variables.test.js
index bfef5ecd2d8..ba6b1332ccb 100644
--- a/lib/classes/Variables.test.js
+++ b/lib/classes/Variables.test.js
@@ -155,6 +155,17 @@ describe('Variables', () => {
       expect(newProperty).to.equal('my stage is dev');
     });
 
+    it('should populate number variables as sub string', () => {
+      const serverless = new Serverless();
+      const valueToPopulate = 5;
+      const matchedString = '${opt:number}';
+      const property = 'your account number is ${opt:number}';
+
+      const newProperty = serverless.variables
+        .populateVariable(property, matchedString, valueToPopulate);
+      expect(newProperty).to.equal('your account number is 5');
+    });
+
     it('should populate non string variables', () => {
       const serverless = new Serverless();
       const valueToPopulate = 5;
@@ -166,11 +177,11 @@ describe('Variables', () => {
       expect(newProperty).to.equal(5);
     });
 
-    it('should throw error if populating non string variable as sub string', () => {
+    it('should throw error if populating non string or non number variable as sub string', () => {
       const serverless = new Serverless();
-      const valueToPopulate = 5;
-      const matchedString = '${opt:number}';
-      const property = 'hello ${opt:number}';
+      const valueToPopulate = {};
+      const matchedString = '${opt:object}';
+      const property = 'your account number is ${opt:object}';
       expect(() => serverless.variables
         .populateVariable(property, matchedString, valueToPopulate))
         .to.throw(Error);