def deploy(project=None, commit=None): """ Deploy a specific version in the specified environment. """ version(project) # Prompt for the commit ID if not given as a parameter. if not commit: commit = prompt('Enter commit to deploy (40 character SHA1)', validate=r'^[0-9a-fA-F]{6,40}$') require('user', 'hosts', 'webroot', 'role', used_for='These variables are used for finding the target deployment environment.', ) make_path = time.strftime('ding-%Y%m%d%H%M')[:-1] cwd = os.path.join(env.build_path, env.project, 'build') abs_make_path = os.path.join(cwd, make_path) with cd(cwd): # Update git checkout. run('git fetch') run('git checkout %s' % commit) # Run the build process via drush make. logging.info('Starting build in %s' % abs_make_path) run('./ding_build.py -lL %s -m profile %s' % (env.role, make_path)) run('curl -s http://localhost/apc_clear_cache.php') logging.warning('%(site)s | %(user)s | %(commit)s' % { 'site': env.webroot.split('/')[-1], 'user': _get_system_username(), 'commit': commit[0:7], })
def deploy(project=None, commit=None): """ Deploy a specific version in the specified environment. """ version(project) # Prompt for the commit ID if not given as a parameter. if not commit: commit = prompt('Enter commit to deploy (40 character SHA1)', validate=r'^[0-9a-fA-F]{6,40}$') require('user', 'hosts', 'webroot', 'role', used_for='These variables are used for finding the target deployment environment.', ) make_path = time.strftime('ding-%Y%m%d%H%M')[:-1] profile_path = os.path.join(env.build_path, env.project) abs_make_path = os.path.join(profile_path, 'build', make_path) with cd(profile_path): # Update git checkout. run('git fetch') run('git checkout %s' % commit) # Run the build process via drush make. logging.info('Starting build in %s' % abs_make_path) run('./ding_build.py -lL %s -m profile %s' % (env.role, make_path)) run('curl -s http://localhost/apc_clear_cache.php') logging.warning('%(site)s | %(user)s | %(commit)s' % { 'site': env.webroot.split('/')[-1], 'user': _get_system_username(), 'commit': commit[0:7], })
def test_host_string_normalization(self): username = _get_system_username() for description, input, output_ in ( ("Sanity check: equal strings remain equal", "localhost", "localhost"), ("Empty username is same as get_system_username", "localhost", username + "@localhost"), ("Empty port is same as port 22", "localhost", "localhost:22"), ("Both username and port tested at once, for kicks", "localhost", username + "@localhost:22"), ): eq_.description = "Host-string normalization: %s" % description yield eq_, normalize(input), normalize(output_) del eq_.description
def test_host_string_denormalization(self): username = _get_system_username() for description, string1, string2 in ( ("Sanity check: equal strings remain equal", "localhost", "localhost"), ("Empty username is same as get_system_username", "localhost:22", username + "@localhost:22"), ("Empty port is same as port 22", "user@localhost", "user@localhost:22"), ("Both username and port", "localhost", username + "@localhost:22"), ("IPv6 address", "2001:DB8::1", username + "@[2001:DB8::1]:22"), ): eq_.description = "Host-string denormalization: %s" % description yield eq_, denormalize(string1), denormalize(string2) del eq_.description
def test_host_string_denormalization(): username = _get_system_username() for description, string1, string2 in ( ("Sanity check: equal strings remain equal", 'localhost', 'localhost'), ("Empty username is same as get_system_username", 'localhost:22', username + '@localhost:22'), ("Empty port is same as port 22", 'user@localhost', 'user@localhost:22'), ("Both username and port", 'localhost', username + '@localhost:22'), ): eq_.description = "Host-string denormalization: %s" % description yield eq_, denormalize(string1), denormalize(string2) del eq_.description
def test_host_string_normalization(): username = _get_system_username() for description, input, output in ( ("Sanity check: equal strings remain equal", 'localhost', 'localhost'), ("Empty username is same as get_system_username", 'localhost', username + '@localhost'), ("Empty port is same as port 22", 'localhost', 'localhost:22'), ("Both username and port tested at once, for kicks", 'localhost', username + '@localhost:22'), ): eq_.description = "Host-string normalization: %s" % description yield eq_, normalize(input), normalize(output) del eq_.description
def test_host_string_normalization(): username = _get_system_username() for description, string1, string2 in ( ("Sanity check: equal strings remain equal", 'localhost', 'localhost'), ("Empty username is same as get_system_username", 'localhost', username + '@localhost'), ("Empty port is same as port 22", 'localhost', 'localhost:22'), ("Both username and port tested at once, for kicks", 'localhost', username + '@localhost:22'), ): eq_.description = description yield eq_, normalize(string1), normalize(string2) del eq_.description
def test_host_string_denormalization(self): username = _get_system_username() for description, string1, string2 in ( ("Sanity check: equal strings remain equal", 'localhost', 'localhost'), ("Empty username is same as get_system_username", 'localhost:22', username + '@localhost:22'), ("Empty port is same as port 22", 'user@localhost', 'user@localhost:22'), ("Both username and port", 'localhost', username + '@localhost:22'), ): eq_.description = "Host-string denormalization: %s" % description yield eq_, denormalize(string1), denormalize(string2) del eq_.description
def test_normalization_for_ipv6(self): """ normalize() will accept IPv6 notation and can separate host and port """ username = _get_system_username() for description, input, output_ in ( ("Full IPv6 address", '2001:DB8:0:0:0:0:0:1', (username, '2001:DB8:0:0:0:0:0:1', '22')), ("IPv6 address in short form", '2001:DB8::1', (username, '2001:DB8::1', '22')), ("IPv6 localhost", '::1', (username, '::1', '22')), ("Square brackets are required to separate non-standard port from IPv6 address", '[2001:DB8::1]:1222', (username, '2001:DB8::1', '1222')), ("Username and IPv6 address", 'user@2001:DB8::1', ('user', '2001:DB8::1', '22')), ("Username and IPv6 address with non-standard port", 'user@[2001:DB8::1]:1222', ('user', '2001:DB8::1', '1222')), ): eq_.description = "Host-string IPv6 normalization: %s" % description yield eq_, normalize(input), output_ del eq_.description
class WovenCommand(BaseCommand): option_list = BaseCommand.option_list + ( make_option( '--noinput', action='store_false', dest='interactive', default=True, help='Do NOT prompt for input (except password entry if required)' ), make_option('-r', '--reject-unknown-hosts', action='store_true', default=False, help="reject unknown hosts"), make_option('-D', '--disable-known-hosts', action='store_true', default=False, help="do not load user known_hosts file"), make_option('-i', action='append', dest='key_filename', default=None, help="path to SSH private key file."), make_option('-u', '--user', default=state._get_system_username(), help="username to use when connecting to remote hosts"), make_option('-p', '--password', default=None, help="password for use with authentication and/or sudo"), make_option( '--setup', help= 'The /path/to/dir containing the setup.py module. The command will execute from this directory. Only required if you are not executing the command from below the setup.py directory', ), ) help = "" args = "host1 [host2 ...] or user@host1 ..." requires_model_validation = False def handle_host(self, *args, **options): """ This will be executed per host - override in subclass """ def parse_host_args(self, *args): """ Returns a comma separated string of hosts """ return ','.join(args) def handle(self, *args, **options): """ Initializes the fabric environment """ self.style = no_style() #manage.py execution specific variables #verbosity 0 = No output at all, 1 = woven output only, 2 = Fabric outputlevel = everything except debug state.env.verbosity = int(options.get('verbosity', 1)) #show_traceback = options.get('traceback', False) state.env.INTERACTIVE = options.get('interactive') #Fabric options #Django passes in a dictionary instead of the optparse options objects for option in options: state.env[option] = options[option] #args will be tuple. We convert it to a comma separated string for fabric all_role_hosts = [] if args: #subclasses can implement parse_host_args to strip out subcommands comma_hosts = self.parse_host_args(*args) normalized_host_list = comma_hosts.split(',') for r in normalized_host_list: #define a list of hosts for given roles if hasattr(settings, 'ROLEDEFS') and settings.ROLEDEFS.get(r): all_role_hosts += settings.ROLEDEFS[r] state.env['roles'] = state.env['roles'] + [r] #simple single host else: all_role_hosts.append(r) #if no args are given we'll use either a 'default' roledef/role_node #or as last resort we'll use a simple HOSTS list elif hasattr(settings, 'ROLEDEFS') and settings.ROLEDEFS.get('default'): all_role_hosts = settings.ROLEDEFS['default'] state.env['roles'] = ['default'] elif hasattr(settings, 'HOSTS') and settings.HOSTS: all_role_hosts = settings.HOSTS else: print "Error: You must include a host or role in the command line or set HOSTS or ROLEDEFS in your settings file" sys.exit(1) state.env['hosts'] = all_role_hosts #This next section is taken pretty much verbatim from fabric.main #so we follow an almost identical but more limited execution strategy #We now need to load django project woven settings into env #This is the equivalent to module level execution of the fabfile.py. #If we were using a fabfile.py then we would include set_env() if int(state.env.verbosity) < 2: with hide('warnings', 'running', 'stdout', 'stderr'): set_env(settings, state.env.setup) else: set_env(settings, state.env.setup) #Back to the standard execution strategy # Set host list (also copy to env) state.env.all_hosts = hosts = state.env.hosts # If hosts found, execute the function on each host in turn for host in hosts: # Preserve user prev_user = state.env.user # Split host string and apply to env dict #TODO - This section is replaced by network.interpret_host_string in Fabric 1.0 username, hostname, port = normalize(host) state.env.host_string = host state.env.host = hostname state.env.user = username state.env.port = port # Actually run command if int(state.env.verbosity) < 2: with hide('warnings', 'running', 'stdout', 'stderr'): self.handle_host(*args, **options) else: self.handle_host(*args, **options) # Put old user back state.env.user = prev_user