github.com/aneshas/cli@v0.0.0-20180104210444-aec958fa47db/langs/base.go (about)

     1  package langs
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  )
     8  
     9  // not a map because some helpers can handle multiple keys
    10  var helpers = []LangHelper{}
    11  
    12  func init() {
    13  	registerHelper(&DotNetLangHelper{})
    14  	registerHelper(&GoLangHelper{})
    15  	registerHelper(&JavaLangHelper{version: "1.8"})
    16  	registerHelper(&JavaLangHelper{version: "9"})
    17  	registerHelper(&LambdaNodeHelper{})
    18  	registerHelper(&NodeLangHelper{})
    19  	registerHelper(&PhpLangHelper{})
    20  	registerHelper(&PythonLangHelper{Version: "2.7.13"})
    21  	registerHelper(&PythonLangHelper{Version: "3.6"})
    22  	registerHelper(&RubyLangHelper{})
    23  	registerHelper(&RustLangHelper{})
    24  
    25  }
    26  
    27  func registerHelper(h LangHelper) {
    28  	helpers = append(helpers, h)
    29  }
    30  
    31  func Helpers() []LangHelper {
    32  	return helpers
    33  }
    34  
    35  var (
    36  	ErrBoilerplateExists = errors.New("Function boilerplate already exists")
    37  )
    38  
    39  // GetLangHelper returns a LangHelper for the passed in language
    40  func GetLangHelper(lang string) LangHelper {
    41  	for _, h := range helpers {
    42  		if h.Handles(lang) {
    43  			return h
    44  		}
    45  	}
    46  	return nil
    47  }
    48  
    49  // LangHelper is the interface that language helpers must implement.
    50  type LangHelper interface {
    51  	// Handles return whether it can handle the passed in lang string or not
    52  	Handles(string) bool
    53  	// LangStrings returns list of supported language strings user can use for runtime
    54  	LangStrings() []string
    55  	// Extension is the file extension this helper supports. Eg: .java, .go, .js
    56  	Extensions() []string
    57  	// Runtime that will be used for the build (includes version)
    58  	Runtime() string
    59  	// BuildFromImage is the base image to build off, typically fnproject/LANG:dev
    60  	BuildFromImage() (string, error)
    61  	// RunFromImage is the base image to use for deployment (usually smaller than the build images)
    62  	RunFromImage() (string, error)
    63  	// If set to false, it will use a single Docker build step, rather than multi-stage
    64  	IsMultiStage() bool
    65  	// Dockerfile build lines for building dependencies or anything else language specific
    66  	DockerfileBuildCmds() []string
    67  	// DockerfileCopyCmds will run in second/final stage of multi-stage build to copy artifacts form the build stage
    68  	DockerfileCopyCmds() []string
    69  	// Entrypoint sets the Docker Entrypoint. One of Entrypoint or Cmd is required.
    70  	Entrypoint() (string, error)
    71  	// Cmd sets the Docker command. One of Entrypoint or Cmd is required.
    72  	Cmd() (string, error)
    73  	// DefaultFormat provides the default fn format to set in func.yaml fn init, return "" for an empty format.
    74  	DefaultFormat() string
    75  	HasPreBuild() bool
    76  	PreBuild() error
    77  	AfterBuild() error
    78  	// HasBoilerplate indicates whether a language has support for generating function boilerplate.
    79  	HasBoilerplate() bool
    80  	// GenerateBoilerplate generates basic function boilerplate. Returns ErrBoilerplateExists if the function file
    81  	// already exists.
    82  	GenerateBoilerplate() error
    83  	// FixImagesOnInit determines if images should be fixed on initialization - BuildFromImage and RunFromImage will be written to func.yaml
    84  	FixImagesOnInit() bool
    85  }
    86  
    87  func defaultHandles(h LangHelper, lang string) bool {
    88  	for _, s := range h.LangStrings() {
    89  		if lang == s {
    90  			return true
    91  		}
    92  	}
    93  	return false
    94  }
    95  
    96  // BaseHelper is empty implementation of LangHelper for embedding in implementations.
    97  type BaseHelper struct {
    98  }
    99  
   100  func (h *BaseHelper) IsMultiStage() bool            { return true }
   101  func (h *BaseHelper) DockerfileBuildCmds() []string { return []string{} }
   102  func (h *BaseHelper) DockerfileCopyCmds() []string  { return []string{} }
   103  func (h *BaseHelper) Entrypoint() (string, error)   { return "", nil }
   104  func (h *BaseHelper) Cmd() (string, error)          { return "", nil }
   105  func (h *BaseHelper) HasPreBuild() bool             { return false }
   106  func (h *BaseHelper) PreBuild() error               { return nil }
   107  func (h *BaseHelper) AfterBuild() error             { return nil }
   108  func (h *BaseHelper) HasBoilerplate() bool          { return false }
   109  func (h *BaseHelper) GenerateBoilerplate() error    { return nil }
   110  func (h *BaseHelper) DefaultFormat() string         { return "" }
   111  func (h *BaseHelper) FixImagesOnInit() bool         { return false }
   112  
   113  // exists checks if a file exists
   114  func exists(name string) bool {
   115  	if _, err := os.Stat(name); err != nil {
   116  		if os.IsNotExist(err) {
   117  			return false
   118  		}
   119  	}
   120  	return true
   121  }
   122  
   123  func dockerBuildError(err error) error {
   124  	return fmt.Errorf("error running docker build: %v", err)
   125  }