diff --git a/.gitignore b/.gitignore index 0bb75ea..f7ad223 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /bin/ /.shards/ *.dwarf +tmp/ diff --git a/examples/hello_cr/funko.yml b/examples/hello_cr/funko.yml new file mode 100644 index 0000000..44354bb --- /dev/null +++ b/examples/hello_cr/funko.yml @@ -0,0 +1,2 @@ +name: hello +runtime: crystal diff --git a/templates/crystal/Dockerfile b/runtimes/crystal/Dockerfile similarity index 100% rename from templates/crystal/Dockerfile rename to runtimes/crystal/Dockerfile diff --git a/templates/crystal/main.cr b/runtimes/crystal/main.cr similarity index 100% rename from templates/crystal/main.cr rename to runtimes/crystal/main.cr diff --git a/templates/crystal/shard.yml b/runtimes/crystal/shard.yml similarity index 100% rename from templates/crystal/shard.yml rename to runtimes/crystal/shard.yml diff --git a/shard.lock b/shard.lock index 045111e..3e68c9c 100644 --- a/shard.lock +++ b/shard.lock @@ -9,6 +9,6 @@ shards: version: 0.4.0 docr: - git: https://github.com/marghidanu/docr.git - version: 0.1.1+git.commit.59fb466b748d5d29a8f2de88a54b71dbfe0285aa + git: https://github.com/ralsina/docr.git + version: 0.1.1+git.commit.18f15cc7111b1d0c63347c7cca07aee9ec87a7a8 diff --git a/shard.yml b/shard.yml index e273562..f426b0b 100644 --- a/shard.yml +++ b/shard.yml @@ -16,5 +16,6 @@ license: MIT dependencies: docr: github: ralsina/docr + branch: add_exposed_ports commander: github: mrrooijen/commander diff --git a/src/faaso.cr b/src/faaso.cr index bdd1987..cb3c5b9 100644 --- a/src/faaso.cr +++ b/src/faaso.cr @@ -3,6 +3,7 @@ require "docr" require "docr/utils.cr" require "file_utils" require "uuid" +require "./funko.cr" # TODO: Write documentation for `Faaso` module Faaso @@ -19,22 +20,46 @@ module Faaso end def run - @arguments.each do |arg| - # A function is a folder with stuff in it - # TODO: decide template based on file extensions or other metadata - template = "templates/crystal" - tmp_dir = "tmp/#{UUID.random}" - slug = arg.gsub("/", "_").strip("_") - repo = "localhost:5000" - tag = "#{repo}/#{slug}:latest" - puts "Building function... #{arg} in #{tmp_dir}" - Dir.mkdir_p("tmp") unless File.exists? "tmp" - FileUtils.cp_r(template, tmp_dir) - Dir.glob(arg + "/**/*").each do |file| - FileUtils.cp(file, tmp_dir) + funkos = Funko.from_paths(@arguments) + funkos.each do |funko| + # Create temporary build location + tmp_dir = Path.new("tmp", UUID.random.to_s) + Dir.mkdir_p(tmp_dir) unless File.exists? tmp_dir + + # Copy runtime if requested + if !funko.runtime.nil? + runtime_dir = Path.new("runtimes", funko.runtime.to_s) + if !File.exists? runtime_dir + puts "Error: runtime #{funko.runtime} not found" + next + end + Dir.glob("#{runtime_dir}/*").each { |src| + FileUtils.cp_r(src, tmp_dir) + } end + + # Copy funko + if funko.path.empty? + puts "Internal error: empty funko path for #{funko.name}" + next + end + Dir.glob("#{funko.path}/*").each { |src| + FileUtils.cp_r(src, tmp_dir) + } + + puts "Building function... #{funko.name} in #{tmp_dir}" + + slug = funko.name + + # FIXME: this should be configurable + repo = "localhost:5000" + tag = "#{repo}/#{funko.name}:latest" + docker_api = Docr::API.new(Docr::Client.new) - docker_api.images.build(context: tmp_dir, tags: [tag, "#{slug}:latest"]) { } + docker_api.images.build( + context: tmp_dir.to_s, + tags: [tag, "#{funko.name}:latest"]) { } + puts "Pushing to repo as #{tag}" docker_api.images.tag(repo: repo, name: slug, tag: "latest") # FIXME: pushing is broken because my test registry has no auth diff --git a/src/funko.cr b/src/funko.cr new file mode 100644 index 0000000..bcbbb19 --- /dev/null +++ b/src/funko.cr @@ -0,0 +1,38 @@ +require "yaml" + +class Funko + include YAML::Serializable + + # Required, the name of the funko. Must be unique across FaaSO + property name : String + + # if Nil, it has no template whatsoever + property runtime : (String | Nil)? = nil + + # Port of the funko process (optional, default is 3000) + property port : UInt32? = 3000 + + # Extra packages, passed as EXTRA_PACKAGES argument + # to the Dockerfile, use it for installing things in + # the SHIPPED docker image + property extra_packages : Array(String)? + + # Extra packages, passed as DEVEL_PACKAGES argument + # to the Dockerfile, use it for installing things in + # the docker stage used to build the code + property devel_packages : Array(String)? + + # Where this is located in the filesystem + @[YAML::Field(ignore: true)] + property path : String = "" + + def self.from_paths(paths : Array(String | Path)) : Array(Funko) + paths.map { |path| Path.new(path, "funko.yml") } + .select { |path| File.exists?(path) } + .map { |path| + f = Funko.from_yaml(File.read(path.to_s)) + f.path = path.parent.to_s + f + } + end +end