From 09f67725e369d0e618078d15cb9f6cf135991383 Mon Sep 17 00:00:00 2001 From: Jin Hian Lee Date: Sun, 15 Feb 2015 18:14:42 +0000 Subject: [PATCH 1/5] Initial support for Dokku PaaS (https://github.com/progrium/dokku) Usage: figaro dokku:set --server= --app= Limitations: 1. Requires Dokku server and app to be specified via --app and --server 2. Requires Dokku server to be accessible via ssh from the client machine for the 'dokku' user Future enhancements could include supporting arbitrary users (which would require dynamically changing the command) and potentially reading the app and server values from the client/shell ENV --- lib/figaro/cli.rb | 34 +++++++++++++++ lib/figaro/cli/dokku_set.rb | 35 ++++++++++++++++ spec/figaro/cli/dokku_set_spec.rb | 69 +++++++++++++++++++++++++++++++ spec/support/bin/ssh | 5 +++ 4 files changed, 143 insertions(+) create mode 100644 lib/figaro/cli/dokku_set.rb create mode 100644 spec/figaro/cli/dokku_set_spec.rb create mode 100644 spec/support/bin/ssh diff --git a/lib/figaro/cli.rb b/lib/figaro/cli.rb index a3a5f54c..d6fd7f2b 100644 --- a/lib/figaro/cli.rb +++ b/lib/figaro/cli.rb @@ -37,5 +37,39 @@ def install require "figaro/cli/heroku_set" HerokuSet.run(options) end + + # figaro dokku:set + + desc "dokku:set --app= --server=", "Send Figaro configuration to a Dokku app." + long_desc <<-LONGDESC + Sends the Figaro configuration to a Dokku app named on Dokku server . + + Since Dokku does not provide a client, this command requires that: + 1. the local machine has ssh access to the Dokku server for the 'dokku' user + 2. the Dokku server (e.g. dokku-example.com) + 3. the app name + LONGDESC + + method_option "app", + required: true, + aliases: ["-a"], + desc: "Specify a Dokku app" + method_option "environment", + aliases: ["-e"], + desc: "Specify an application environment" + method_option "path", + aliases: ["-p"], + default: "config/application.yml", + desc: "Specify a configuration file path" + method_option "server", + required: true, + aliases: ["-s"], + desc: "Specify a Dokku server (dokku-example.com)" + + define_method "dokku:set" do + require "figaro/cli/dokku_set" + DokkuSet.run(options) + end + end end diff --git a/lib/figaro/cli/dokku_set.rb b/lib/figaro/cli/dokku_set.rb new file mode 100644 index 00000000..5bfdede8 --- /dev/null +++ b/lib/figaro/cli/dokku_set.rb @@ -0,0 +1,35 @@ +require "figaro/cli/task" + +module Figaro + class CLI < Thor + class DokkuSet < Task + def run + system(configuration, command) + end + + private + + def command + "ssh #{ssh_creds} config:set #{for_app} #{vars}" + end + + def ssh_creds + # hard code the dokku user because a non-dokku user requires the 'dokku' command + # TODO: support alternative users and automatically add the 'dokku' command + options[:server] ? "dokku@#{options[:server]}" : nil + end + + def for_app + options[:app] ? "#{options[:app]}" : nil + end + + def vars + configuration.keys.map { |k| var(k) }.join(" ") + end + + def var(key) + Gem.win_platform? ? %(#{key}="%#{key}%") : %(#{key}="$#{key}") + end + end + end +end diff --git a/spec/figaro/cli/dokku_set_spec.rb b/spec/figaro/cli/dokku_set_spec.rb new file mode 100644 index 00000000..d6c129fc --- /dev/null +++ b/spec/figaro/cli/dokku_set_spec.rb @@ -0,0 +1,69 @@ +describe "figaro dokku:set" do + before do + create_dir("example") + cd("example") + write_file("config/application.yml", "foo: bar") + + # setup cmd-line base + @cli_input_base = "figaro dokku:set --app=foo-bar-app --server=dokku-server" + # setup common expected values + @cmd = "ssh" + @args_base = ["dokku@dokku-server", "config:set", "foo-bar-app"] + end + + it "sends Figaro configuration to a Dokku app" do + run_simple(@cli_input_base) + + command = commands.last + expect(command.name).to eq(@cmd) + expect(command.args).to eq(@args_base << "foo=bar") + end + + it "fails if a Dokku app is not specified" do + run_simple("figaro dokku:set --server=dokku-server") + + command = commands.last + expect(command).to be_nil + end + + it "fails if a Dokku server is not specified" do + run_simple("figaro dokku:set --app=foo-bar-app") + + command = commands.last + expect(command).to be_nil + end + + it "respects path" do + write_file("env.yml", "foo: bar") + + run_simple(@cli_input_base + " -p env.yml") + + command = commands.last + expect(command.name).to eq(@cmd) + expect(command.args).to eq(@args_base << "foo=bar") + end + + it "respects environment" do + overwrite_file("config/application.yml", <<-EOF) +foo: bar +test: + foo: baz +EOF + + run_simple(@cli_input_base + " -e test") + + command = commands.last + expect(command.name).to eq(@cmd) + expect(command.args).to eq(@args_base << "foo=baz") + end + + it "handles values with special characters" do + overwrite_file("config/application.yml", "foo: bar baz") + + run_simple(@cli_input_base) + + command = commands.last + expect(command.name).to eq(@cmd) + expect(command.args).to eq(@args_base << "foo=bar baz") + end +end diff --git a/spec/support/bin/ssh b/spec/support/bin/ssh new file mode 100644 index 00000000..f97c1b35 --- /dev/null +++ b/spec/support/bin/ssh @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby + +require File.expand_path("../../command_interceptor", __FILE__) + +CommandInterceptor.intercept("ssh") From 879eaa5ae4bf8fcff8253703eabfb93ceb0a16ad Mon Sep 17 00:00:00 2001 From: Jin Hian Lee Date: Sun, 15 Feb 2015 19:20:19 +0000 Subject: [PATCH 2/5] Update README to add a Dokku section Also fix (as best as possible) minor command line help formatting issues --- README.md | 28 +++++++++++++++++++++++++++- lib/figaro/cli.rb | 22 +++++++++++----------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c47d56ca..35e522e9 100644 --- a/README.md +++ b/README.md @@ -167,9 +167,35 @@ For more information: $ figaro help heroku:set ``` +#### Dokku + +[Dokku](https://github.com/progrium/dokku), like Heroku, provides a way to set application configuration ENV variables via the command line. However, there is no local client at this moment, so you need to run the commands remotely via ssh. + +```bash +$ ssh config:set google_analytics_key=UA-35722661-5 +``` + +Using the `figaro` command, you can set values from your configuration file all at once: + +```bash +$ figaro dokku:set --server= --app= -e production +``` + +For more information: + +```bash +$ figaro help dokku:set +``` + +In this initial implementation, you need to: + +1. Explicitly specify the Dokku server and app via the --app and --server options +1. Ensure that the 'dokku' user can ssh into the Dokku server from the local machine (this involves ensuring that the local user's ssh key is in the list of the Dokku server's authorized keys) + + #### Other Hosts -If you're not deploying to Heroku, you have two options: +If you're not deploying to Heroku or Dokku, you have two options: * Generate a remote configuration file * Set `ENV` variables directly diff --git a/lib/figaro/cli.rb b/lib/figaro/cli.rb index d6fd7f2b..d8b8565e 100644 --- a/lib/figaro/cli.rb +++ b/lib/figaro/cli.rb @@ -40,20 +40,24 @@ def install # figaro dokku:set - desc "dokku:set --app= --server=", "Send Figaro configuration to a Dokku app." + desc "dokku:set", "Send Figaro configuration to a Dokku app." long_desc <<-LONGDESC - Sends the Figaro configuration to a Dokku app named on Dokku server . + Sends the Figaro configuration to a Dokku APP on the Dokku SERVER. - Since Dokku does not provide a client, this command requires that: - 1. the local machine has ssh access to the Dokku server for the 'dokku' user - 2. the Dokku server (e.g. dokku-example.com) - 3. the app name + Since Dokku does not provide a client, this command requires that:\n\n + 1. the 'dokku' user can ssh into the Dokku server from the local machine\n\n + 2. the Dokku server (e.g. dokku-example.com) and app name (e.g. my-app) are specified + \n\n LONGDESC + method_option "server", + required: true, + aliases: ["-s"], + desc: "Specify a Dokku server (e.g. dokku-example.com)" method_option "app", required: true, aliases: ["-a"], - desc: "Specify a Dokku app" + desc: "Specify a Dokku app (e.g. my-dokku-app)" method_option "environment", aliases: ["-e"], desc: "Specify an application environment" @@ -61,10 +65,6 @@ def install aliases: ["-p"], default: "config/application.yml", desc: "Specify a configuration file path" - method_option "server", - required: true, - aliases: ["-s"], - desc: "Specify a Dokku server (dokku-example.com)" define_method "dokku:set" do require "figaro/cli/dokku_set" From 898ea6c11729ad875384902704c35b217dfb068e Mon Sep 17 00:00:00 2001 From: morizyun Date: Sun, 10 Jan 2016 00:54:59 +0900 Subject: [PATCH 3/5] support dokku cli command --- lib/figaro/cli.rb | 12 ++------ lib/figaro/cli/dokku_set.rb | 2 +- spec/figaro/cli/dokku_set_spec.rb | 48 +++++++++---------------------- spec/support/bin/{ssh => dokku} | 2 +- 4 files changed, 18 insertions(+), 46 deletions(-) rename spec/support/bin/{ssh => dokku} (69%) mode change 100644 => 100755 diff --git a/lib/figaro/cli.rb b/lib/figaro/cli.rb index d8b8565e..e96ef040 100644 --- a/lib/figaro/cli.rb +++ b/lib/figaro/cli.rb @@ -45,19 +45,11 @@ def install Sends the Figaro configuration to a Dokku APP on the Dokku SERVER. Since Dokku does not provide a client, this command requires that:\n\n - 1. the 'dokku' user can ssh into the Dokku server from the local machine\n\n - 2. the Dokku server (e.g. dokku-example.com) and app name (e.g. my-app) are specified + 1. Add git remote dokku repository\n\n + 2. Do following command `gem install dokku-cli` \n\n LONGDESC - method_option "server", - required: true, - aliases: ["-s"], - desc: "Specify a Dokku server (e.g. dokku-example.com)" - method_option "app", - required: true, - aliases: ["-a"], - desc: "Specify a Dokku app (e.g. my-dokku-app)" method_option "environment", aliases: ["-e"], desc: "Specify an application environment" diff --git a/lib/figaro/cli/dokku_set.rb b/lib/figaro/cli/dokku_set.rb index 5bfdede8..ac6bd3c1 100644 --- a/lib/figaro/cli/dokku_set.rb +++ b/lib/figaro/cli/dokku_set.rb @@ -10,7 +10,7 @@ def run private def command - "ssh #{ssh_creds} config:set #{for_app} #{vars}" + "dokku #{ssh_creds} config:set #{for_app} #{vars}" end def ssh_creds diff --git a/spec/figaro/cli/dokku_set_spec.rb b/spec/figaro/cli/dokku_set_spec.rb index d6c129fc..ac6f8d90 100644 --- a/spec/figaro/cli/dokku_set_spec.rb +++ b/spec/figaro/cli/dokku_set_spec.rb @@ -3,44 +3,24 @@ create_dir("example") cd("example") write_file("config/application.yml", "foo: bar") - - # setup cmd-line base - @cli_input_base = "figaro dokku:set --app=foo-bar-app --server=dokku-server" - # setup common expected values - @cmd = "ssh" - @args_base = ["dokku@dokku-server", "config:set", "foo-bar-app"] - end - - it "sends Figaro configuration to a Dokku app" do - run_simple(@cli_input_base) - - command = commands.last - expect(command.name).to eq(@cmd) - expect(command.args).to eq(@args_base << "foo=bar") - end - - it "fails if a Dokku app is not specified" do - run_simple("figaro dokku:set --server=dokku-server") - - command = commands.last - expect(command).to be_nil end - it "fails if a Dokku server is not specified" do - run_simple("figaro dokku:set --app=foo-bar-app") + it "sends Figaro configuration to dokku" do + run_simple("figaro dokku:set") command = commands.last - expect(command).to be_nil + expect(command.name).to eq("dokku") + expect(command.args).to eq(["config:set", "foo=bar"]) end it "respects path" do write_file("env.yml", "foo: bar") - run_simple(@cli_input_base + " -p env.yml") + run_simple("figaro dokku:set -p env.yml") command = commands.last - expect(command.name).to eq(@cmd) - expect(command.args).to eq(@args_base << "foo=bar") + expect(command.name).to eq("dokku") + expect(command.args).to eq(["config:set", "foo=bar"]) end it "respects environment" do @@ -48,22 +28,22 @@ foo: bar test: foo: baz -EOF + EOF - run_simple(@cli_input_base + " -e test") + run_simple("figaro dokku:set -e test") command = commands.last - expect(command.name).to eq(@cmd) - expect(command.args).to eq(@args_base << "foo=baz") + expect(command.name).to eq("dokku") + expect(command.args).to eq(["config:set", "foo=baz"]) end it "handles values with special characters" do overwrite_file("config/application.yml", "foo: bar baz") - run_simple(@cli_input_base) + run_simple("figaro dokku:set") command = commands.last - expect(command.name).to eq(@cmd) - expect(command.args).to eq(@args_base << "foo=bar baz") + expect(command.name).to eq("dokku") + expect(command.args).to eq(["config:set", "foo=bar baz"]) end end diff --git a/spec/support/bin/ssh b/spec/support/bin/dokku old mode 100644 new mode 100755 similarity index 69% rename from spec/support/bin/ssh rename to spec/support/bin/dokku index f97c1b35..b8c3540c --- a/spec/support/bin/ssh +++ b/spec/support/bin/dokku @@ -2,4 +2,4 @@ require File.expand_path("../../command_interceptor", __FILE__) -CommandInterceptor.intercept("ssh") +CommandInterceptor.intercept("dokku") From 6e71bcbf8ca9871ac9fcca3e03ddded7e0a82be5 Mon Sep 17 00:00:00 2001 From: morizyun Date: Sun, 10 Jan 2016 01:41:26 +0900 Subject: [PATCH 4/5] fixing README --- README.md | 11 +++++------ lib/figaro/cli.rb | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2cd047ac..c919f69a 100644 --- a/README.md +++ b/README.md @@ -169,16 +169,16 @@ $ figaro help heroku:set #### Dokku -[Dokku](https://github.com/progrium/dokku), like Heroku, provides a way to set application configuration ENV variables via the command line. However, there is no local client at this moment, so you need to run the commands remotely via ssh. +[Dokku](https://github.com/progrium/dokku), like Heroku, provides a way to set application configuration ENV variables via the command line. ```bash -$ ssh config:set google_analytics_key=UA-35722661-5 +$ dokku config:set google_analytics_key=UA-35722661-5 ``` Using the `figaro` command, you can set values from your configuration file all at once: ```bash -$ figaro dokku:set --server= --app= -e production +$ figaro dokku:set -e production ``` For more information: @@ -189,9 +189,8 @@ $ figaro help dokku:set In this initial implementation, you need to: -1. Explicitly specify the Dokku server and app via the --app and --server options -1. Ensure that the 'dokku' user can ssh into the Dokku server from the local machine (this involves ensuring that the local user's ssh key is in the list of the Dokku server's authorized keys) - +1. Add git remote dokku repository => `git remote add dokku dokku@example-dokku-server.com:example-app` +2. Do following command => `gem install dokku-cli` #### Other Hosts diff --git a/lib/figaro/cli.rb b/lib/figaro/cli.rb index 2c1e23ea..42cdfc10 100644 --- a/lib/figaro/cli.rb +++ b/lib/figaro/cli.rb @@ -46,8 +46,8 @@ def install Sends the Figaro configuration to a Dokku APP on the Dokku SERVER. Since Dokku does not provide a client, this command requires that:\n\n - 1. Add git remote dokku repository\n\n - 2. Do following command `gem install dokku-cli` + 1. Add git remote dokku repository => `git remote add dokku dokku@example-dokku-server.com:example-app`\n\n + 2. Do following command => `gem install dokku-cli` \n\n LONGDESC From d838c63c274b418b94e9dad56c3b8adc0ea5e4a8 Mon Sep 17 00:00:00 2001 From: morizyun Date: Sun, 10 Jan 2016 02:03:02 +0900 Subject: [PATCH 5/5] fixing wrapper of dokku cli command --- lib/figaro/cli/dokku_set.rb | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/figaro/cli/dokku_set.rb b/lib/figaro/cli/dokku_set.rb index ac6bd3c1..5962150d 100644 --- a/lib/figaro/cli/dokku_set.rb +++ b/lib/figaro/cli/dokku_set.rb @@ -10,17 +10,7 @@ def run private def command - "dokku #{ssh_creds} config:set #{for_app} #{vars}" - end - - def ssh_creds - # hard code the dokku user because a non-dokku user requires the 'dokku' command - # TODO: support alternative users and automatically add the 'dokku' command - options[:server] ? "dokku@#{options[:server]}" : nil - end - - def for_app - options[:app] ? "#{options[:app]}" : nil + "dokku config:set #{vars}" end def vars