[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Fab-user] [PATCH] Fix #7: Implement "something like roles."
From: |
Christian Vest Hansen |
Subject: |
Re: [Fab-user] [PATCH] Fix #7: Implement "something like roles." |
Date: |
Thu, 6 Nov 2008 22:08:48 +0100 |
Your absolutely right.
This really should be a different decorator.
On Thu, Nov 6, 2008 at 9:48 PM, Jeff Forcier <address@hidden> wrote:
> One potential problem with this approach is that it makes it very easy
> to make mistakes; if the only differentiation between
> strings-as-rolenames and strings-as-hostnames is whether you use
> (string) varargs or a list argument, I can see a lot of people (yours
> truly possibly included :)) accidentally doing one when they mean the
> other.
>
> Making matters worse is that such a mistake would be very hard to
> catch and provide a meaningful error message for, which IMHO is the
> only saving grace for potentially confusing features -- if you can
> catch the obvious mistake easily and thus not waste as much of the
> user's time, that's usually Good Enough.
>
> I'd personally prefer to do what I think Cap does, and provide both
> @hosts and @roles to lessen the ambiguity (where @roles would do
> exactly what your patch does -- just lets you refer to the name of a
> config variable which is a list of hostnames). I do not recall what
> Cap does to allow mixing of roles and explicit server names (or IF it
> does so) but it'd definitely be good to allow mixing the two if at all
> possible.
I think mixing @roles and @hosts should produce a union set of the two.
>
> -Jeff
>
> On Thu, Nov 6, 2008 at 3:32 PM, Christian Vest Hansen
> <address@hidden> wrote:
>> Actually, what this gives is a way to simulate roles.
>>
>> We allow fab_hosts (and other places) to be a string rather
>> than a list of hosts. This string will then be used to
>> look up a variable that contains the real list of hosts to
>> connect to.
>>
>> So we can have fabfiles like this:
>>
>> config.servers = ['localhost', '127.0.0.1']
>> def prod():
>> config.servers = ['...', '...']
>> @hosts('servers')
>> def deploy():
>> run('stuff on $(fab_host)')
>>
>> Here, we are allowed to define as many variables with lists
>> of hosts as we want, and we can change them any time we want.
>> ---
>> TODO | 3 ---
>> doc/samples/roles/fabfile.py | 14 ++++++--------
>> fabric.py | 18 +++++++++++++-----
>> 3 files changed, 19 insertions(+), 16 deletions(-)
>>
>> diff --git a/TODO b/TODO
>> index 183a74d..ea4969e 100644
>> --- a/TODO
>> +++ b/TODO
>> @@ -1,7 +1,4 @@
>> 1 Ctrl-C dosn't quite work... especially not with the tail example
>> -7 need something like roles in Capistrano
>> - - I'm thinking the ability to work with variable environments as
>> first class
>> - objects
>> 9 make parallel submode work
>> 11 add built-in help for built-in variables
>> - and modes and submodes
>> diff --git a/doc/samples/roles/fabfile.py b/doc/samples/roles/fabfile.py
>> index 169fa8a..fd54c53 100644
>> --- a/doc/samples/roles/fabfile.py
>> +++ b/doc/samples/roles/fabfile.py
>> @@ -1,27 +1,25 @@
>>
>> # Our server roles:
>> -rdbms = ['127.0.0.1']
>> -httpd = ['localhost']
>> +config.rdbms = ['127.0.0.1']
>> +config.httpd = ['localhost']
>>
>> def production():
>> # this would set `rdbms` and `httpd` to prod. values.
>> # for now we just switch them around in order to observe the effect
>> - global httpd, rdbms
>> - rdbms, httpd = httpd, rdbms
>> - # ... except, this dosn't actually work :(
>> + config.rdbms, config.httpd = config.httpd, config.rdbms
>>
>> def build():
>> local('echo Building project')
>>
>> address@hidden(*rdbms)
>> address@hidden('rdbms')
>> def prepare_db():
>> run("echo Preparing database for deployment")
>>
>> address@hidden(*httpd)
>> address@hidden('httpd')
>> def prepare_web():
>> run("echo Preparing web servers for deployment")
>>
>> @depends(prepare_db, prepare_web)
>> address@hidden(*httpd)
>> address@hidden('httpd')
>> def deploy():
>> run("echo Doing final deployment things to $(fab_host)")
>> diff --git a/fabric.py b/fabric.py
>> index 952f94b..c1ae55a 100644
>> --- a/fabric.py
>> +++ b/fabric.py
>> @@ -1250,21 +1250,29 @@ def _args_hash(args):
>> return hash(tuple(sorted(args.items())))
>>
>> def _execute_at_target(command, args):
>> - ENV['fab_local_mode'] = getattr(command, 'mode', ENV['fab_mode'])
>> - ENV['fab_local_hosts'] = getattr(command, 'hosts', ENV.get('fab_hosts'))
>> + mode = ENV['fab_local_mode'] = getattr(command, 'mode', ENV['fab_mode'])
>> + hosts = ENV['fab_local_hosts'] = getattr(
>> + command, 'hosts', ENV.get('fab_hosts'))
>> + if hosts and len(hosts) == 1 and isinstance(hosts[0], basestring):
>> + # we allow the hosts to be a string-alias for another variable
>> + # that will contain the real array of hosts to connect to.
>> + host_alias = _lazy_format(hosts[0])
>> + hosts = ENV.get(host_alias)
>> + print "Resoling host alias", host_alias, "to", (', '.join(hosts))
>> + ENV['fab_local_hosts'] = hosts
>> # Determine whether we need to connect for this command, do so if so
>> if _needs_connect(command):
>> _check_fab_hosts()
>> _connect()
>> - if ENV['fab_local_mode'] in ('rolling', 'fanout'):
>> + if mode in ('rolling', 'fanout'):
>> print("Warning: The 'rolling' and 'fanout' fab_modes are " +
>> "deprecated.\n Use 'broad' and 'deep' instead.")
>> ENV['fab_local_mode'] = 'broad'
>> # Run command once, with each operation running once per host.
>> - if ENV['fab_local_mode'] == 'broad':
>> + if mode == 'broad':
>> command(**(args or {}))
>> # Run entire command once per host.
>> - elif ENV['fab_local_mode'] == 'deep':
>> + elif mode == 'deep':
>> # Gracefully handle local-only commands
>> if CONNECTIONS:
>> for host_conn in CONNECTIONS:
>> --
>> 1.6.0.1
>>
>> _______________________________________________
>> Fab-user mailing list
>> address@hidden
>> http://lists.nongnu.org/mailman/listinfo/fab-user
>>
>>
>
--
Venlig hilsen / Kind regards,
Christian Vest Hansen.