Initial import

This commit is contained in:
Glenn Y. Rolland 2020-03-02 00:21:13 +01:00
commit deff96f550
5 changed files with 228 additions and 0 deletions

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2020 Glenn Y. Rolland
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

11
Makefile Normal file
View file

@ -0,0 +1,11 @@
all: build
build:
crystal src/pushokku.cr -o pushokku
test:
run:
crystal run src/pushokku.cr

27
README.md Normal file
View file

@ -0,0 +1,27 @@
# pushokku
TODO: Write a description here
## Installation
TODO: Write installation instructions here
## Usage
TODO: Write usage instructions here
## Development
TODO: Write development instructions here
## Contributing
1. Fork it (<https://github.com/glenux/pushokku/fork>)
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
## Contributors
- [Glenn Y. Rolland](https://github.com/glenux) - creator and maintainer

13
shard.yml Normal file
View file

@ -0,0 +1,13 @@
name: pushokku
version: 0.1.0
authors:
- Glenn Y. Rolland <glenux@glenux.net>
targets:
pushokku:
main: src/pushokku.cr
crystal: 0.31.1
license: MIT

156
src/pushokku.cr Normal file
View file

@ -0,0 +1,156 @@
# file: help.cr
require "option_parser"
require "yaml"
class Pushokku
alias Options = {
config_file: String,
docker_compose_yml: String,
environment: String
}
alias Config = {
host: String,
service: String,
app: String
}
def parse_options(args) : Options
config_file = ".pushokku"
docker_compose_yml = "docker-compose.yml"
environment = "production"
OptionParser.parse(args) do |parser|
parser.banner = "Welcome to Pushokku!"
parser.on "-c CONFIG", "--config=CONFIG", "Use the following config file" do |file|
config_file = file
end
parser.on "-f DOCKER_COMPOSE_YML", "--config=DOCKER_COMPOSE_YML", "Use the following docker-compose file" do |file|
docker_compose_yml = file
end
parser.on "-v", "--version", "Show version" do
puts "version 1.0"
exit
end
parser.on "-h", "--help", "Show help" do
puts parser
exit
end
end
return {
docker_compose_yml: docker_compose_yml,
config_file: config_file,
environment: environment
}
end
def load_config(config_file : String) : Config
if ! File.exists? config_file
STDERR.puts "ERROR: Unable to read configuration file '#{config_file}'"
exit 1
end
yaml = File.open(config_file) do |file|
YAML.parse(file)
end
{
host: yaml["host"].to_s,
service: yaml["service"].to_s,
app: yaml["app"].to_s
}
end
def image_tag(docker_compose_yml : String, service : String, app : String)
version = `date +"v%Y%m%d_%H%M"`.strip
tag_name = "dokku/#{app}"
tag_name_version = "#{tag_name}:#{version}"
image = `docker-compose -f #{docker_compose_yml} images -q #{service} `.strip
Process.run "docker", ["tag", image, tag_name_version]
res = {
version: version,
tag_name_version: tag_name_version
}
puts YAML.dump({ image_tag: res })
puts "---"
return res
end
def image_push(host, tag_name_version)
# docker save "$TAG_NAME_VERSION" \
# | gzip \
# | ssh "$HOST_REMOTE" "gunzip | docker load"
pipe1_reader, pipe1_writer = IO.pipe(true)
pipe2_reader, pipe2_writer = IO.pipe(true)
p3_out = IO::Memory.new
p3_err = IO::Memory.new
p3 = Process.new "ssh", [host, "gunzip | docker load"],
input: pipe2_reader, output: p3_out, error: p3_err
p2_err = IO::Memory.new
p2 = Process.new "gzip",
input: pipe1_reader,
output: pipe2_writer,
error: p2_err
p1_err = IO::Memory.new
p1 = Process.new "docker", ["save", tag_name_version],
output: pipe1_writer,
error: p1_err
status = p1.wait
pipe1_writer.close
if status.success?
puts "Docker image successfully exported"
else
STDERR.puts "Error when exporting docker image!"
STDERR.puts "- exit status: #{status.exit_status}"
STDERR.puts "- err: #{p1_err}"
exit 1
end
status = p2.wait
pipe1_reader.close
pipe2_writer.close
if ! status.success?
STDERR.puts "Error when gzipping image!"
STDERR.puts "- exit status: #{status.exit_status}"
STDERR.puts "- err: #{p2_err}"
end
status = p3.wait
pipe2_reader.close
if status.success?
puts "Docker image successfully imported on #{host}"
# puts "- out : #{p3_out}"
else
STDERR.puts "Error when importing docker image!"
STDERR.puts "- exit status: #{status.exit_status}"
STDERR.puts "- err: #{p3_err}"
end
end
def image_deploy(host, app, version)
Process.run "ssh", [host, "dokku tags:deploy #{app} #{version}"]
end
def self.run(args)
app = Pushokku.new
opts = app.parse_options(args)
config = app.load_config(opts["config_file"])
# env_config = App.get_config(config, opts["environment"])
image_meta = app.image_tag(opts["docker_compose_yml"], config["service"], config["app"])
app.image_push(config["host"], image_meta["tag_name_version"])
app.image_deploy(config["host"], config["app"], image_meta["tag_name_version"])
end
end
Pushokku.run(ARGV)