Skip to content

Commit

Permalink
Merge pull request #14 from ciaranRoche/fg-4954-gen-service
Browse files Browse the repository at this point in the history
Generate Service YAML
  • Loading branch information
ciaranRoche authored Feb 4, 2019
2 parents 5d3babb + c1f2f0d commit 6ee4499
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 141 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ To create and push an image to Quay.io
$ r3x create -p -q -n <<Repo Name or Org>>
```

### Deploy a Function as a Container
On success of the create command, a `service.yaml` file is generated and can be used to deploy the Function to Knative. For full instructions on this process see our [Documentation](https://github.com/rubixFunctions/r3x-docs/blob/master/install/README.md)

Alternatively, a Function as a Container can be run like any other container using a runtime like Docker, for example:
```
$ docker run -t -p 8080:8080 <<image tag>>
```


## License
This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details

65 changes: 44 additions & 21 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/term"
"golang.org/x/crypto/ssh/terminal"
"io"
"os"
"syscall"

Expand Down Expand Up @@ -96,11 +97,24 @@ func create(name string, push bool, quay bool) {
if quay {
imageName = "quay.io/" + name + "/" + funcName
} else {
imageName = name + "/" + funcName
imageName = "docker.io/" + name + "/" + funcName
}
dockerBuildContext, err := os.Open("/tmp/archieve.tar")
defer dockerBuildContext.Close()

cli, _ := client.NewClientWithOpts(client.FromEnv)

buildImage(imageName, cli, dockerBuildContext)

if push {
pushImage(name, pass, imageName, cli)
}

genServiceYaml(name, imageName)

}

func buildImage(imageName string, cli client.ImageAPIClient, dockerBuildContext io.Reader){
options := types.ImageBuildOptions{
SuppressOutput: false,
Remove: true,
Expand All @@ -116,31 +130,40 @@ func create(name string, push bool, quay bool) {
termFd, isTerm := term.GetFdInfo(os.Stderr)
jsonmessage.DisplayJSONMessagesStream(buildResponse.Body, os.Stderr, termFd, isTerm, nil)

if push {
authString := types.AuthConfig{
Username: name,
Password: pass,
}
encodedJSON, err := json.Marshal(authString)
if err != nil {
panic(err)
}
authStr := base64.URLEncoding.EncodeToString(encodedJSON)
}

pushOptions := types.ImagePushOptions{
RegistryAuth: authStr,
}
func pushImage(name string, pass string, imageName string, cli client.ImageAPIClient){
authString := types.AuthConfig{
Username: name,
Password: pass,
}
encodedJSON, err := json.Marshal(authString)
if err != nil {
panic(err)
}
authStr := base64.URLEncoding.EncodeToString(encodedJSON)

pushResponse, err := cli.ImagePush(context.Background(), imageName, pushOptions)
if err != nil {
fmt.Printf("%s", err.Error())
}
fmt.Println("Pushing Image has Started")
termFD, isTErm := term.GetFdInfo(os.Stderr)
jsonmessage.DisplayJSONMessagesStream(pushResponse, os.Stderr, termFD, isTErm, nil)
pushOptions := types.ImagePushOptions{
RegistryAuth: authStr,
}

pushResponse, err := cli.ImagePush(context.Background(), imageName, pushOptions)
if err != nil {
fmt.Printf("%s", err.Error())
}
fmt.Println("Pushing Image has Started")
termFD, isTErm := term.GetFdInfo(os.Stderr)
jsonmessage.DisplayJSONMessagesStream(pushResponse, os.Stderr, termFD, isTErm, nil)
}

func genServiceYaml(name string, image string){
schema := LoadSchema()
switch schema.FuncType {
case "js":
createJSServiceYAML(name, image)
default:
fmt.Println("Error parsing Schema, no service.yaml generated")
}
}

func getPass() string {
Expand Down
164 changes: 164 additions & 0 deletions cmd/function_types_javascript.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright © 2019 RubiXFunctions
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"log"
"os"
"path/filepath"
)

func InitializeJSFunction(function *Function, schema *Schema){
if !exists(function.AbsPath()) {
err := os.MkdirAll(function.AbsPath(), os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
} else if !isEmpty(function.AbsPath()) {
fmt.Println("Function can not be bootstrapped in a non empty direcctory: " + function.AbsPath())
return
}

createJSDockerfile(function)
createJSMain(function)
createJSSchema(schema, function)
createJSPackageJSON(function)
createLicense(function)
fmt.Println(`Your Function is ready at` + function.AbsPath())
}

func createJSDockerfile(function *Function) {

dockerTemplate := `FROM node:alpine
WORKDIR /usr/src/app
COPY . .
RUN npm install --only=production
ENV PORT 8080
EXPOSE $PORT
CMD [ "npm", "start" ]`


createFile(function, dockerTemplate, "Dockerfile")
}

func createJSMain(function *Function){
jSTemplate := `const r3x = require('@rubixfunctions/r3x-js-sdk')
let schema
r3x.execute(function(){
let response = {'message' : 'Hello r3x function'}
return response
}, schema)`
createFile(function, jSTemplate, "r3x-func.js")
}

func createJSServiceYAML(name string, image string){
wd, err := os.Getwd()
if err != nil {
log.Print(err)
return
}
data := make(map[string]interface{})
data["name"] = name
data["image"] = image
var serviceYaml = `apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: {{.name}}
namespace: default
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
image: {{.image}}`

rootCmdScript, err := executeTemplate(serviceYaml, data)
if err != nil {
fmt.Println(err)
}

err = writeStringToFile(filepath.Join(wd, "service.yaml"), rootCmdScript)
if err != nil {
fmt.Println(err)
}

fmt.Println("schema.json generated")
}

func createJSSchema(schema *Schema, function *Function){
data := make(map[string]interface{})
data["name"] = schema.Name
data["funcType"] = schema.FuncType
data["response"] = schema.Response
var schemaJson = `{
"name" : "{{.name}}",
"funcType" : "{{.funcType}}",
"response" : "{{.response}}"
}`

rootCmdScript, err := executeTemplate(schemaJson, data)
if err != nil {
fmt.Println(err)
}

err = writeStringToFile(filepath.Join(function.AbsPath(), "schema.json"), rootCmdScript)
if err != nil {
fmt.Println(err)
}
}

func createJSPackageJSON(function *Function) {
tempPackageTemplate := `{
"name": "{{ .name}}",
"version": "0.0.1",
"description": "r3x Knative Function",
"main": "r3x-func.js",
"scripts": {
"start": "node r3x-func.js"
},
"keywords": [
"javascript",
"knative",
"kubernetes",
"serverless"
],
"dependencies": {
"@rubixfunctions/r3x-js-sdk": "0.0.9"
}
}
`

data := make(map[string]interface{})
data["name"] = function.name

rootCmdScript, err := executeTemplate(tempPackageTemplate, data)
if err != nil {
fmt.Println(err)
}

err = writeStringToFile(filepath.Join(function.AbsPath(), "package.json"), rootCmdScript)
if err != nil {
fmt.Println(err)
}
}
Loading

0 comments on commit 6ee4499

Please sign in to comment.