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
Sunzi run #22
Sunzi run #22
Conversation
sunzi.run is an idempotent solution for running bash functions. This allows someone to isolate provisioning concerns into distinct functions which can be safely executed via sunzi.run over N number of sunzi deploys to the same server.
I'm not sure if having a persistent state at a remote server is a good idea. It can make things harder - you'd need to ssh to the server when something went wrong. For instance, # install.sh
function my.custom_recipe() {
A
B
C
}
sunzi.run "my.custom_recipe" What would you do if A and B passed, but C failed? If it was my responsibility to ensure the atomicity of # install.sh
# A
# B
C and re-run. Of course, I don't commit those changes to Also, leaving the state on the server is incompatible with |
I have scenarios where some of my provisioning functions run once, some every time, & others where I frequently add new functions. Some of my use cases are complex enough that commenting just doesn't scale well. It's nice to simply use the |
OK, now that's related to the topic we talked on a separate ticket - I'd use Capistrano for that kind of repetitive tasks. For instance, I have
namespace :config do
task :default do
...
unicorn
...
end
task :unicorn do
run "cp -f #{current_release}/ops/config/unicorn/unicorn.sh /etc/init.d/unicorn && chmod +x /etc/init.d/unicorn"
end Because capistrano fits better for those tasks, when you want to copy and replace those files from the git repository. Sunzi basically only runs once at the provisioning phase, and all the rest are handled by capistrano. Sunzi shouldn't be a swiss army knife that does everything... Does that make sense? |
I agree with the idea of limiting Sunzi's scope to the narrowest set. I concede that for some environments copying config files & init scripts might be app specific. Using a tool like Capistrano for such cases is probably more appropriate than using Sunzi. Having said that... a common use case that I use "re-provisioning" (with Sunzi) for is to copy our canonical authorized_keys file to the "developer" user account onto my servers. All of our developers ssh to our servers with this account. By re-provisioning with Sunzi (using a I suppose my Chef knowledge is skewing my opinion on this. I think of provisioning as a tool to manage the server's evolution (independent of app deployment concerns) rather than a 1 time thing that runs on first boot. This is why idempotency is an important goal for me. It has been very helpful to get your insight on what Sunzi is intended to be. I prefer it's simplicity to other tools like Chef, but I'm currently using it to accomplish some of the same goals. I'm really hoping there is a middle ground that will let me have my cake & eat it too. |
Actually, I use Capistrano for that too. task :ssh do
require 'open-uri'
keys = ['kenn', 'hopsoft'].map do |name|
open("https://github.com/#{name}.keys").read
end.join("\n") << "\n"
put keys, '/root/.ssh/authorized_keys', mode: 0600
end By directly retrieving SSH keys from Github, Keeping everything idempotent has become perceived as too much effort, and now I'm more leaning toward Immutable Infrastructure, where every infrastructure is provisioned once and only once. Disposing it upon each app deploy sounds too extreme, but I get the idea very well - I've been always doing "create a new app server then add to the cluster, then eliminate the old one" kind of approach. For that pattern, Sunzi works perfectly - better at purchasing new instances rather than maintaining the old instances. |
I'm sold on the immutable infrastructure approach & have been experimenting with Docker for some of my personal projects to accomplish this. Thanks for your insights on this pull request. |
Added a
sunzi.run
function as a simple idempotent solution for running bash functions. Simply define a specific provisioning operation in a bash function & then callsunzi.run
like so.Invoking a fuction with
sunzi.run
only executes the function once regardless of how many timessunzi deploy
is run. The implementation simply touches a file at/etc/sunzi_run/FUNCTION_NAME
& then checks for the existence of this file to determine whether or not to run the function.This simple idempotency solution has proved invaluable for me, making Sunzi a viable alternative to heavier tools like Chef & Puppet.