adding ruby runtime (#983)

* adding ruby runtime

* checking http and/or https

* debugging

* dropping unnecessary runtime structure

* removing debugging messages

* removing debugging messages

* adding check if its a valid URL or not

* checking if url is not valid using ParseRequestURI
diff --git a/parsers/manifest_parser.go b/parsers/manifest_parser.go
index 3223225..ff2124b 100644
--- a/parsers/manifest_parser.go
+++ b/parsers/manifest_parser.go
@@ -38,6 +38,7 @@
 	"github.com/apache/incubator-openwhisk-wskdeploy/wskenv"
 	"github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
 	"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
+	"net/url"
 )
 
 const (
@@ -234,7 +235,8 @@
 		} else if dependencies.LocationIsGithub(location) {
 
 			// TODO() define const for the protocol prefix, etc.
-			if !strings.HasPrefix(location, HTTPS) && !strings.HasPrefix(location, HTTP) {
+			_, err := url.ParseRequestURI(location)
+			if err != nil {
 				location = HTTPS + dependency.Location
 				location = wskenv.InterpolateStringWithEnvVar(location).(string)
 			}
diff --git a/runtimes/runtimes.go b/runtimes/runtimes.go
index 361c614..5f2ef7f 100644
--- a/runtimes/runtimes.go
+++ b/runtimes/runtimes.go
@@ -22,6 +22,7 @@
 	"encoding/json"
 	"io/ioutil"
 	"net/http"
+	"net/url"
 	"strings"
 	"time"
 
@@ -42,6 +43,13 @@
 	JAR_FILE_EXTENSION      = "jar"
 	PHP_FILE_EXTENSION      = "php"
 	ZIP_FILE_EXTENSION      = "zip"
+	RUBY_FILE_EXTENSION     = "rb"
+	NODEJS_RUNTIME          = "nodejs"
+	SWIFT_RUNTIME           = SWIFT_FILE_EXTENSION
+	PYTHON_RUNTIME          = "python"
+	JAVA_RUNTIME            = JAVA_FILE_EXTENSION
+	PHP_RUNTIME             = PHP_FILE_EXTENSION
+	RUBY_RUNTIME            = "ruby"
 	HTTP_CONTENT_TYPE_KEY   = "Content-Type"
 	HTTP_CONTENT_TYPE_VALUE = "application/json; charset=UTF-8"
 	RUNTIME_NOT_SPECIFIED   = "NOT SPECIFIED"
@@ -58,11 +66,8 @@
 }
 
 type Runtime struct {
-	Image      string `json:"image"`
 	Deprecated bool   `json:"deprecated"`
-	ReMain     bool   `json:"requireMain"`
 	Default    bool   `json:"default"`
-	Attach     bool   `json:"attached"`
 	Kind       string `json:"kind"`
 }
 
@@ -88,8 +93,12 @@
 // `curl -k https://openwhisk.ng.bluemix.net`
 // hard coding it here in case of network unavailable or failure.
 func ParseOpenWhisk(apiHost string) (op OpenWhiskInfo, err error) {
-	url := HTTPS + apiHost
-	req, _ := http.NewRequest("GET", url, nil)
+	opURL := apiHost
+	_, err = url.ParseRequestURI(opURL)
+	if err != nil {
+		opURL = HTTPS + opURL
+	}
+	req, _ := http.NewRequest("GET", opURL, nil)
 	req.Header.Set(HTTP_CONTENT_TYPE_KEY, HTTP_CONTENT_TYPE_VALUE)
 	tlsConfig := &tls.Config{
 		InsecureSkipVerify: true,
@@ -139,7 +148,7 @@
 		b, _ := ioutil.ReadAll(res.Body)
 		if b != nil && len(b) > 0 {
 			stdout := wski18n.T(wski18n.ID_MSG_UNMARSHAL_NETWORK_X_url_X,
-				map[string]interface{}{"url": url})
+				map[string]interface{}{"url": opURL})
 			wskprint.PrintOpenWhiskInfo(stdout)
 			err = json.Unmarshal(b, &op)
 			if err != nil {
@@ -182,17 +191,19 @@
 func FileExtensionRuntimes(op OpenWhiskInfo) (ext map[string]string) {
 	ext = make(map[string]string)
 	for k := range op.Runtimes {
-		if strings.Contains(k, NODEJS_FILE_EXTENSION) {
+		if strings.Contains(k, NODEJS_RUNTIME) {
 			ext[NODEJS_FILE_EXTENSION] = k
-		} else if strings.Contains(k, PYTHON_FILE_EXTENSION) {
+		} else if strings.Contains(k, PYTHON_RUNTIME) {
 			ext[PYTHON_FILE_EXTENSION] = k
-		} else if strings.Contains(k, SWIFT_FILE_EXTENSION) {
+		} else if strings.Contains(k, SWIFT_RUNTIME) {
 			ext[SWIFT_FILE_EXTENSION] = k
-		} else if strings.Contains(k, PHP_FILE_EXTENSION) {
+		} else if strings.Contains(k, PHP_RUNTIME) {
 			ext[PHP_FILE_EXTENSION] = k
-		} else if strings.Contains(k, JAVA_FILE_EXTENSION) {
+		} else if strings.Contains(k, JAVA_RUNTIME) {
 			ext[JAVA_FILE_EXTENSION] = k
 			ext[JAR_FILE_EXTENSION] = k
+		} else if strings.Contains(k, RUBY_RUNTIME) {
+			ext[RUBY_FILE_EXTENSION] = k
 		}
 	}
 	return
@@ -204,16 +215,18 @@
 	for k, v := range op.Runtimes {
 		for i := range v {
 			if !v[i].Deprecated {
-				if strings.Contains(k, NODEJS_FILE_EXTENSION) {
+				if strings.Contains(k, NODEJS_RUNTIME) {
 					rte[v[i].Kind] = NODEJS_FILE_EXTENSION
-				} else if strings.Contains(k, PYTHON_FILE_EXTENSION) {
+				} else if strings.Contains(k, PYTHON_RUNTIME) {
 					rte[v[i].Kind] = PYTHON_FILE_EXTENSION
-				} else if strings.Contains(k, SWIFT_FILE_EXTENSION) {
+				} else if strings.Contains(k, SWIFT_RUNTIME) {
 					rte[v[i].Kind] = SWIFT_FILE_EXTENSION
-				} else if strings.Contains(k, PHP_FILE_EXTENSION) {
+				} else if strings.Contains(k, PHP_RUNTIME) {
 					rte[v[i].Kind] = PHP_FILE_EXTENSION
-				} else if strings.Contains(k, JAVA_FILE_EXTENSION) {
+				} else if strings.Contains(k, JAVA_RUNTIME) {
 					rte[v[i].Kind] = JAVA_FILE_EXTENSION
+				} else if strings.Contains(k, RUBY_RUNTIME) {
+					rte[v[i].Kind] = RUBY_FILE_EXTENSION
 				}
 			}
 		}
diff --git a/runtimes/runtimes.json b/runtimes/runtimes.json
index 857331f..e916759 100644
--- a/runtimes/runtimes.json
+++ b/runtimes/runtimes.json
@@ -10,122 +10,217 @@
     "runtimes": {
         "nodejs": [
             {
-                "image": "openwhisk/nodejsaction:latest",
+                "kind": "nodejs",
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "nodejsaction",
+                    "tag": "latest"
+                },
                 "deprecated": true,
-                "requireMain": false,
-                "default": false,
-                "attached": false,
-                "kind": "nodejs"
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
             },
             {
-                "image": "openwhisk/nodejs6action:latest",
-                "deprecated": false,
-                "requireMain": false,
+                "kind": "nodejs:6",
                 "default": true,
-                "attached": false,
-                "kind": "nodejs:6"
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "nodejs6action",
+                    "tag": "latest"
+                },
+                "deprecated": false,
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                },
+                "stemCells": [{
+                    "count": 2,
+                    "memory": "256 MB"
+                }]
             },
             {
-                "image": "ibmfunctions/action-nodejs-v8:1.13.0",
-                "deprecated": false,
-                "requireMain": false,
+                "kind": "nodejs:8",
                 "default": false,
-                "attached": false,
-                "kind": "nodejs:8"
-            }
-        ],
-        "java": [
-            {
-                "image": "openwhisk/java8action:latest",
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "action-nodejs-v8",
+                    "tag": "latest"
+                },
                 "deprecated": false,
-                "requireMain": true,
-                "default": true,
-                "attached": true,
-                "kind": "java"
-            }
-        ],
-        "php": [
-            {
-                "image": "openwhisk/action-php-v7.1:latest",
-                "deprecated": false,
-                "requireMain": false,
-                "default": true,
-                "attached": false,
-                "kind": "php:7.1"
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
             }
         ],
         "python": [
             {
-                "image": "openwhisk/python2action:latest",
+                "kind": "python",
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "python2action",
+                    "tag": "latest"
+                },
                 "deprecated": false,
-                "requireMain": false,
-                "default": false,
-                "attached": false,
-                "kind": "python"
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
             },
             {
-                "image": "openwhisk/python2action:latest",
-                "deprecated": false,
-                "requireMain": false,
+                "kind": "python:2",
                 "default": true,
-                "attached": false,
-                "kind": "python:2"
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "python2action",
+                    "tag": "latest"
+                },
+                "deprecated": false,
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
             },
             {
-                "image": "openwhisk/python3action:latest",
+                "kind": "python:3",
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "python3action",
+                    "tag": "latest"
+                },
                 "deprecated": false,
-                "requireMain": false,
-                "default": false,
-                "attached": false,
-                "kind": "python:3"
-            },
-            {
-                "image": "ibmfunctions/action-python-v3:1.6.0",
-                "deprecated": false,
-                "requireMain": false,
-                "default": false,
-                "attached": false,
-                "kind": "python-jessie:3"
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
             }
         ],
         "swift": [
             {
-                "image": "openwhisk/swiftaction:latest",
+                "kind": "swift",
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "swiftaction",
+                    "tag": "latest"
+                },
                 "deprecated": true,
-                "requireMain": false,
-                "default": false,
-                "attached": false,
-                "kind": "swift"
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
             },
             {
-                "image": "openwhisk/swift3action:latest",
+                "kind": "swift:3",
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "swift3action",
+                    "tag": "latest"
+                },
                 "deprecated": true,
-                "requireMain": false,
-                "default": false,
-                "attached": false,
-                "kind": "swift:3"
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
             },
             {
-                "image": "openwhisk/action-swift-v3.1.1:latest",
+                "kind": "swift:3.1.1",
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "action-swift-v3.1.1",
+                    "tag": "latest"
+                },
                 "deprecated": false,
-                "requireMain": false,
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
+            },
+            {
+                "kind": "swift:4.1",
                 "default": true,
-                "attached": false,
-                "kind": "swift:3.1.1"
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "action-swift-v4.1",
+                    "tag": "latest"
+                },
+                "deprecated": false,
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
+            }
+        ],
+        "java": [
+            {
+                "kind": "java",
+                "default": true,
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "java8action",
+                    "tag": "latest"
+                },
+                "deprecated": false,
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                },
+                "requireMain": true
+            }
+        ],
+        "php": [
+            {
+                "kind": "php:7.1",
+                "default": false,
+                "deprecated": false,
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "action-php-v7.1",
+                    "tag": "latest"
+                },
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
             },
             {
-                "image": "ibmfunctions/action-swift-v4.1:1.5.0",
+                "kind": "php:7.2",
+                "default": true,
                 "deprecated": false,
-                "requireMain": false,
-                "default": false,
-                "attached": false,
-                "kind": "swift:4.1"
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "action-php-v7.2",
+                    "tag": "latest"
+                },
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                }
+            }
+        ],
+        "ruby": [
+            {
+                "kind": "ruby:2.5",
+                "default": true,
+                "deprecated": false,
+                "attached": {
+                    "attachmentName": "codefile",
+                    "attachmentType": "text/plain"
+                },
+                "image": {
+                    "prefix": "openwhisk",
+                    "name": "action-ruby-v2.5",
+                    "tag": "latest"
+                }
             }
         ]
     },
-    "limits": {
-        "actions_per_minute": 5000,
-        "triggers_per_minute": 5000,
-        "concurrent_actions": 1000
-    }
-}
+    "blackboxes": [
+        {
+            "prefix": "openwhisk",
+            "name": "dockerskeleton",
+            "tag": "latest"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/runtimes/runtimes_test.go b/runtimes/runtimes_test.go
index f7650e3..f966e11 100644
--- a/runtimes/runtimes_test.go
+++ b/runtimes/runtimes_test.go
@@ -28,7 +28,7 @@
 	assert.Equal(t, nil, err, "parse openwhisk info error happened.")
 	converted := ConvertToMap(openwhisk)
 	assert.Equal(t, 2, len(converted["nodejs"]), "not expected length")
-	assert.Equal(t, 1, len(converted["php"]), "not expected length")
+	assert.Equal(t, 2, len(converted["php"]), "not expected length")
 	assert.Equal(t, 1, len(converted["java"]), "not expected length")
 	assert.Equal(t, 4, len(converted["python"]), "not expected length")
 	assert.Equal(t, 2, len(converted["swift"]), "not expected length")
diff --git a/tests/src/integration/helloworld/actions/hello.rb b/tests/src/integration/helloworld/actions/hello.rb
new file mode 100644
index 0000000..77a0609
--- /dev/null
+++ b/tests/src/integration/helloworld/actions/hello.rb
@@ -0,0 +1,9 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+
+def main(args)
+  name = args["name"] || "stranger"
+  greeting = "Hello #{name}!"
+  puts greeting
+  { "greeting" => greeting }
+end
diff --git a/tests/src/integration/helloworld/manifest.yaml b/tests/src/integration/helloworld/manifest.yaml
index e29a64b..9179be0 100644
--- a/tests/src/integration/helloworld/manifest.yaml
+++ b/tests/src/integration/helloworld/manifest.yaml
@@ -139,10 +139,21 @@
             payload:
               type: string
               description: a simple greeting message, Hello stranger!
+        helloRuby:
+          function: actions/hello.rb
+        helloRubyWithCode:
+          code: |
+                def main(args)
+                  name = args["name"] || "stranger"
+                  greeting = "Hello #{name}!"
+                  puts greeting
+                  { "greeting" => greeting }
+                end
+          runtime: ruby:2.5
       sequences:
         # sequence of helloworld in all four runtimes
         hello-world-series:
-          actions: helloNodejs, helloNodejsWithCode, helloJava, helloPython, helloPythonWithCode, helloSwift, helloSwiftWithCode
+          actions: helloNodejs, helloNodejsWithCode, helloJava, helloPython, helloPythonWithCode, helloSwift, helloSwiftWithCode, helloRuby, helloRubyWithCode
       triggers:
         # trigger to activate helloworld sequence
         triggerHelloworld: