sprinkle-tool / sprinkle

Sprinkle is a software provisioning tool you can use to build remote servers with. eg. to install a Rails, or Sinatra stack on a brand new slice directly after its been created
https://github.com/sprinkle-tool/sprinkle
MIT License
1.15k stars 138 forks source link

Is it possible to reference Capistrano config variables? #57

Open sbleon opened 12 years ago

sbleon commented 12 years ago

Some of my packages need to know where I'm deploying my Rails app to so that they can create directories, write config files, etc. I can't figure out how to refer to Capistrano's "deploy_to" variable from inside my packages.

I can reference "deploy_to" from within the deployment definition as @style.config.fetch(:deploy_to). It also looks like the instance of Deployment (that contains @style) is passed into Package#process (http://rubydoc.info/gems/sprinkle/0.4.2/Sprinkle/Package/Package:process).

Is there a good way (or even a bad way, frankly) to refer to "deploy_to" and other Cap variables?

phillbaker commented 12 years ago

Looks like this might be a solution https://github.com/blahutka/sprinkle_packages/blob/master/lib/sprinkle_packages/capistrano.rb

phillbaker commented 12 years ago

More specifically, a quick monkeypatch in your policy file (install.rb commonly), before your packages are required:

#Monkey patch...
module Sprinkle::Package
  class Package
    @@capistrano = {}

    def self.set_variables=(set)
      @@capistrano = set
    end

    def self.fetch(name)
      @@capistrano[name]
    end

    def self.exists?(name)
      @@capistrano.key?(name)
    end
  end
end

then, in your deploy.rb add:

Sprinkle::Package::Package.set_variables = self.variables

and access set :user, 'bob' from packages with: Package.fetch(:user)

One note: the deployment {...} block in the policy file (again, typically install.rb), must precede requiring the packages and policy {...} block. If you have the deployment block after the packages/policies everything will compile, but you'll be pulling nil values for the variables.

sbleon commented 12 years ago

@phillbaker, thanks for the suggestion! That worked pretty nicely.

manuelmeurer commented 11 years ago

Is this possible without monkeypatching in the newer versions of Sprinkle?

joshgoebel commented 11 years ago

Are you wanting to read or change them? I'm not sure packages should be changing Capistrano settings (without a monkey patch), though I can see the desire to read them. No great way to do this yet since Package doesn't have access to the actor until policy passes it during the actual installs.

It seems very weird to have retrieval methods in package that only work with a single actor though. How would this work with other actors?

joshgoebel commented 11 years ago

Once the actual logistics were worked out I think the Cap actor would have to monkey patch (via module) Package itself to add the functionality to access the Cap config.

manuelmeurer commented 11 years ago

Yeah, changing would seem weird, but reading the Cap config vars would be appropriate I think. Do you have time to look at this in more detail? Otherwise I could have a look at the code and see if I could implement something.

joshgoebel commented 11 years ago

I don't have time right now. I think making Deployment a singleton would be one approach... then inside package (via module) you'd just have something like:

def cap_config; Deployment::Deployment.instance.style.config; end

Otherwise you have to inject deployment into the package options as package instances are spooled up, which seems icky to me. Though that would never support someone doing something crazy-cool with multiple deployments... problem is packages are kind of designed to be discrete things that do not know about how they are being deployed - and this request kind of wants to draw a bridge across that boundary.

joshgoebel commented 11 years ago

Actually perhaps it should be passed... and in Policy#process the inner block would still call Package#instance but perhaps instance shouldn't eval the block... but rather when Package#process is called @deployment is set locally and then the block is evaled, and then the rest of process happens. That would require reworking some tests though but would preserve maximum flexibility to using the Sprinkle library to do cool crap.

Just some ideas.

manuelmeurer commented 11 years ago

I had a look at the code and I have to admit this is a bit over my head... sorry I can't help you with implementing this. :( I will continue to use the monkeypatch for now.

joshgoebel commented 10 years ago

We really need our own settings API that all actors could take advantage of... Capistrano can't monkey patch Package itself because we don't know what actor we're using until after all the packages are defined... so any type of method like cap_config would have always be available (for all actors), which is messy. But if you had a settings API then the Capistrano actor could hook into that to expose the Capistrano settings, and other actors could provide their own settings interfaces.