Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds 'faas-cli template pull' command (rebase/review PR) #220

Merged
merged 11 commits into from
Nov 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 0 additions & 43 deletions NOTES.md

This file was deleted.

41 changes: 29 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ The CLI can be used to build and deploy functions to [OpenFaaS](https://github.c

Demo: [ASCII cinema](https://asciinema.org/a/141284)

#### TL;DR
### TL;DR - Introductory tutorial

[Blog: Coffee with the FaaS-CLI](https://blog.alexellis.io/quickstart-openfaas-cli/)

### Install the CLI
### Get started: Install the CLI

The easiest way to install the faas-cli is through a curl script or `brew`:

Expand Down Expand Up @@ -43,15 +43,19 @@ The main commands supported by the CLI are:
* `faas-cli remove` - removes the functions from a local or remote OpenFaaS gateway
* `faas-cli invoke` - invokes the functions and reads from STDIN for the body of the request
* `faas-cli login` - stores basic auth credentials for OpenFaaS gateway (supports multiple gateways)
* `faas-cli logout` - removes basic auth credentials fora given gateway
* `faas-cli logout` - removes basic auth credentials for a given gateway

Advanced commands:

* `faas-cli template pull` - pull in templates from a remote GitHub repository

Help for all of the commands supported by the CLI can be found by running:

* `faas-cli help` or `faas-cli [command] --help`

You can chose between using a [programming language template](https://github.com/openfaas/faas-cli/tree/master/template) where you only need to provide a handler file, or a Docker that you can build yourself.

**Templates**
#### Templates

Command: `faas-cli new FUNCTION_NAME --lang python/node/go/ruby/Dockerfile/etc`

Expand All @@ -69,7 +73,20 @@ You can customise the Dockerfile or code for any of the templates. Just create a

See also: `faas-cli new --help`

**Docker image**
**Third-party community templates**

Templates created and maintained by a third-party can be added to your local system using the `faas-cli template pull` command.

Curated language templates:

| Language | Author | URL |
|---|---|---|
| PHP | @itscaro | https://github.com/itscaro/openfaas-template-php/ |
| PHP5 | @itscaro | https://github.com/itscaro/openfaas-template-php/ |

Read more on [community templates here](guide/TEMPLATE.md).

#### Docker image as a function

Specify `lang: Dockerfile` if you want the faas-cli to execute a build or `skip_build: true` for pre-built images.

Expand Down Expand Up @@ -124,7 +141,7 @@ Now you can use the following command to deploy your function(s):
$ faas-cli deploy -f ./samples.yml
```
### Managing secrets
#### Managing secrets
You can deploy secrets and configuration via environmental variables in-line or via external files.
Expand Down Expand Up @@ -165,7 +182,7 @@ functions:
no_proxy: http://gateway/
```

### Constraints
#### Constraints

Constraints work with Docker Swarm and are useful for pinning functions to certain hosts.

Expand All @@ -183,7 +200,7 @@ Or only Windows:
- "node.platform.os == windows"
```

### Labels
#### Labels

Labels can be applied through a map which may be consumed by the back-end scheduler such as Docker Swarm or Kubernetes.

Expand All @@ -195,7 +212,7 @@ For example:
canary: true
```

### YAML reference
#### YAML reference

The possible entries for functions are documented below:

Expand All @@ -217,7 +234,7 @@ functions:

Use environmental variables for setting tokens and configuration.

**Accessing the function with `curl`**
#### Access functions with `curl`

You can initiate a HTTP POST via `curl`:

Expand All @@ -237,10 +254,10 @@ $ uname -a | curl http://localhost:8080/function/nodejs-echo--data-binary @-
> For further instructions on the manual CLI flags (without using a YAML file) read [manual_cli.md](https://github.com/openfaas/faas-cli/blob/master/MANUAL_CLI.md)
## FaaS-CLI Developers / Contributors
### FaaS-CLI Developers / Contributors
See [contributing guide](https://github.com/openfaas/faas-cli/blob/master/CONTRIBUTING.md).
### License
#### License
This project is part of the OpenFaaS project licensed under the MIT License.
52 changes: 27 additions & 25 deletions builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,51 @@ import (
"log"
"os"
"strings"

"github.com/openfaas/faas-cli/stack"
)

// BuildImage construct Docker image from function parameters
func BuildImage(image string, handler string, functionName string, language string, nocache bool, squash bool, shrinkwrap bool) {

switch language {
case "node", "python", "ruby", "csharp", "python3", "go":
tempPath := createBuildTemplate(functionName, handler, language)
if stack.IsValidTemplate(language) {

fmt.Printf("Building: %s with %s template. Please wait..\n", image, language)
var tempPath string
if strings.ToLower(language) == "dockerfile" {

flagStr := buildFlagString(nocache, squash, os.Getenv("http_proxy"), os.Getenv("https_proxy"))
if shrinkwrap {
fmt.Printf("Nothing to do for: %s.\n", functionName)

if shrinkwrap {
fmt.Printf("%s shrink-wrapped to %s\n", functionName, tempPath)
} else {
builder := strings.Split(fmt.Sprintf("docker build %s-t %s .", flagStr, image), " ")
return
}

ExecCommand(tempPath, builder)
fmt.Printf("Image: %s built.\n", image)
}
break
case "Dockerfile", "dockerfile":
if shrinkwrap {
fmt.Printf("Nothing to do for: %s.\n", functionName)
} else {
tempPath := handler
tempPath = handler
if _, err := os.Stat(handler); err != nil {
fmt.Printf("Unable to build %s, %s is an invalid path\n", image, handler)
fmt.Printf("Image: %s not built.\n", image)

break
return
}
fmt.Printf("Building: %s with Dockerfile. Please wait..\n", image)

flagStr := buildFlagString(nocache, squash, os.Getenv("http_proxy"), os.Getenv("https_proxy"))
} else {

builder := strings.Split(fmt.Sprintf("docker build %s-t %s .", flagStr, image), " ")
fmt.Println(strings.Join(builder, " "))
ExecCommand(tempPath, builder)
fmt.Printf("Image: %s built.\n", image)
tempPath = createBuildTemplate(functionName, handler, language)
fmt.Printf("Building: %s with %s template. Please wait..\n", image, language)

if shrinkwrap {
fmt.Printf("%s shrink-wrapped to %s\n", functionName, tempPath)

return
}
}
default:

flagStr := buildFlagString(nocache, squash, os.Getenv("http_proxy"), os.Getenv("https_proxy"))
builder := strings.Split(fmt.Sprintf("docker build %s-t %s .", flagStr, image), " ")
ExecCommand(tempPath, builder)
fmt.Printf("Image: %s built.\n", image)

} else {
log.Fatalf("Language template: %s not supported. Build a custom Dockerfile instead.", language)
}
}
Expand Down
2 changes: 1 addition & 1 deletion commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func PullTemplates(templateUrl string) error {
if err != nil || exists == nil {
log.Println("No templates found in current directory.")

err = fetchTemplates(templateUrl)
err = fetchTemplates(templateUrl, false)
if err != nil {
log.Println("Unable to download templates from Github.")
return err
Expand Down
40 changes: 39 additions & 1 deletion commands/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ var deployCmd = &cobra.Command{
[--handler HANDLER_DIR]
[--fprocess PROCESS]
[--env ENVVAR=VALUE ...]
[--label LABEL=VALUE ...]
[--label LABEL=VALUE ...]
[--replace=false]
[--update=false]
[--constraint PLACEMENT_CONSTRAINT ...]
Expand Down Expand Up @@ -165,6 +165,16 @@ func runDeploy(cmd *cobra.Command, args []string) {
log.Fatalln(envErr)
}

// Get FProcess to use from the ./template/template.yml, if a template is being used
if languageExistsNotDockerfile(function.Language) {
var fprocessErr error
function.FProcess, fprocessErr = deriveFprocess(function)
if fprocessErr != nil {
log.Fatalln(fprocessErr)

}
}

proxy.DeployFunction(function.FProcess, services.Provider.GatewayURL, function.Name, function.Image, function.Language, replace, allEnvironment, services.Provider.Network, functionConstraints, update, secrets, allLabels)
}
} else {
Expand Down Expand Up @@ -282,3 +292,31 @@ func compileEnvironment(envvarOpts []string, yamlEnvironment map[string]string,
functionAndStack := mergeMap(yamlEnvironment, fileEnvironment)
return mergeMap(functionAndStack, envvarArguments), nil
}

func deriveFprocess(function stack.Function) (string, error) {
var fprocess string

pathToTemplateYAML := "./template/" + function.Language + "/template.yml"
if _, err := os.Stat(pathToTemplateYAML); os.IsNotExist(err) {
return "", err
}

var langTemplate stack.LanguageTemplate
parsedLangTemplate, err := stack.ParseYAMLForLanguageTemplate(pathToTemplateYAML)

if err != nil {
return "", err

}

if parsedLangTemplate != nil {
langTemplate = *parsedLangTemplate
fprocess = langTemplate.FProcess
}

return fprocess, nil
}

func languageExistsNotDockerfile(language string) bool {
return len(language) > 0 && strings.ToLower(language) != "dockerfile"
}
Loading