Подтвердить что ты не робот

Поддерживает ли python динамический набор env.hosts?

Я хочу изменить env.hosts динамически, потому что иногда я хочу сначала установить на одну машину, проверить, нормально ли тогда развертывать на многих машинах. В настоящее время мне нужно сначала установить env.hosts, как я могу установить env.hosts в методе, а не в глобальном при запуске script?

4b9b3361

Ответ 1

Да, вы можете установить env.hosts динамически. Мы используем один общий шаблон:

from fabric.api import env

def staging():
    env.hosts = ['XXX.XXX.XXX.XXX', ]

def production():
    env.hosts = ['YYY.YYY.YYY.YYY', 'ZZZ.ZZZ.ZZZ.ZZZ', ]

def deploy():
   # Do something...

Вы использовали бы это, чтобы связать задачи, такие как fab staging deploy или fab production deploy.

Ответ 2

Поздно вечеринке, но я достиг этого с ec2, как это (обратите внимание, что в EC2 вы не знаете, что такое ip/hostname, вообще говоря, так что вам почти нужно идти динамично, чтобы действительно объяснить, как среда/системы могут возникнуть - другой вариант - использовать dyndns, но тогда это все равно будет полезно):

from fabric.api import *
import datetime
import time
import urllib2
import ConfigParser
from platform_util import *

config = ConfigParser.RawConfigParser()

@task
def load_config(configfile=None):
    '''
    ***REQUIRED***  Pass in the configuration to use - usage load_config:</path/to/config.cfg>
    '''
    if configfile != None:
        # Load up our config file
        config.read(configfile)

        # Key/secret needed for aws interaction with boto 
        # (anyone help figure out a better way to do this with sub modules, please don't say classes :-) )
        global aws_key
        global aws_sec

        aws_key = config.get("main","aws_key")
        aws_sec = config.get("main","aws_sec")

         # Stuff for fabric
        env.user                = config.get("main","fabric_ssh_user")
        env.key_filename        = config.get("main","fabric_ssh_key_filename")
        env.parallel            = config.get("main","fabric_default_parallel")

        # Load our role definitions for fabric
        for i in config.sections():
            if i != "main":
                hostlist = []
                if config.get(i,"use-regex") == 'yes':
                    for x in get_running_instances_by_regex(aws_key,aws_sec,config.get(i,"security-group"),config.get(i,"pattern")):
                        hostlist.append(x.private_ip_address)   
                    env.roledefs[i] = hostlist

                else:
                    for x in get_running_instances(aws_key,aws_sec,config.get(i,"security-group")):
                        hostlist.append(x.private_ip_address)   
                    env.roledefs[i] = hostlist

                if config.has_option(i,"base-group"):
                    if config.get(i,"base-group") == 'yes':
                        print "%s is a base group" % i
                        print env.roledefs[i]
#                       env["basegroups"][i] = True

где get_running_instances и get_running_instances_by_regex - это служебные функции, которые используют boto (http://code.google.com/p/boto/)

Пример:

import logging
import re
from boto.ec2.connection import EC2Connection
from boto.ec2.securitygroup import SecurityGroup
from boto.ec2.instance import Instance
from boto.s3.key import Key

########################################
# B-O-F get_instances
########################################
def get_instances(access_key=None, secret_key=None, security_group=None):
    '''
    Get all instances. Only within a security group if specified., doesnt' matter their state (running/stopped/etc)
    '''
    logging.debug('get_instances()')
    conn = EC2Connection(aws_access_key_id=access_key, aws_secret_access_key=secret_key)

    if security_group:
        sg = SecurityGroup(connection=conn, name=security_group)
        instances = sg.instances()
        return instances
    else:
        instances = conn.get_all_instances()
        return instances

Вот пример того, как выглядел мой конфиг:

# Config file for fabric toolset
#
#  This specific configuration is for <whatever> related hosts
#  
#
[main]
aws_key = <key>
aws_sec = <secret>
fabric_ssh_user = <your_user>
fabric_ssh_key_filename = /path/to/your/.ssh/<whatever>.pem
fabric_default_parallel = 1

#
# Groupings - Fabric knows them as roledefs (check env dict)
#

# Production groupings
[app-prod]
security-group = app-prod
use-regex = no
pattern = 

[db-prod]
security-group = db-prod
use-regex = no
pattern = 

[db-prod-masters]
security-group = db-prod
use-regex = yes
pattern = mysql-[d-s]01

Ответ 3

Еще один новый ответ на старый вопрос.:) Но я недавно обнаружил, что пытаюсь динамически устанавливать хосты, и действительно должен не соглашаться с основным ответом. Мое представление о динамике или, по крайней мере, о том, что я пытаюсь сделать, - это получить DNS-имя экземпляра, которое было создано только boto, и получить доступ к этому экземпляру с помощью команды fab. Я не мог сделать fab staging deploy, потому что экземпляр не существует во время редактирования файла.

К счастью, fabric поддерживает действительно динамическое назначение хоста с execute. (Возможно, этого не существовало, когда вопрос сначала был задан, конечно, но теперь он это делает). execute позволяет определить как вызываемую функцию, так и env.hosts, которые она должна использовать для этой команды. Например:

def create_EC2_box(data=fab_base_data):
    conn = boto.ec2.connect_to_region(region)
    reservations = conn.run_instances(image_id=image_id, ...)
    ...
    return instance.public_dns_name

def _ping_box():
    run('uname -a')
    run('tail /var/log/cloud-init-output.log')

def build_box():
    box_name = create_EC2_box(fab_base_data)
    new_hosts = [box_name]
    # new_hosts = ['ec2-54-152-152-123.compute-1.amazonaws.com'] # testing
    execute(_ping_box, hosts=new_hosts)

Теперь я могу сделать fab build_box, и он выпустит один вызов boto, который создает экземпляр, и другой вызов fabric, который запускается в новом экземпляре, - без необходимости определять имя экземпляра во время редактирования.