Como você pode fazer um módulo de execução de sal retornar um código de saída diferente de zero na falha

2

Estou tentando usar o Jenkins para executar um comando do módulo de execução do Salt; se algum lacaio não executar o comando, quero que o trabalho de Jenkins falhe. Jenkins apenas segue a prática geral de scripts de shell de falhar em um código de saída diferente de zero, então, para que ele funcione, Salt também deve.

E é aí que estou preso, executando algo como isso funciona como esperado:

root@salt-master:~# salt --batch-size 1 --failhard -G 'ec2_roles:stage' cmd.run 'exit 0'

Executing run on ['stage-12']

jid:
    20170209212325270060
retcode:
    0
stage-12:

Executing run on ['stage-13']

jid:
    20170209212325423735
retcode:
    0
stage-13:

Executing run on ['stage-197']

jid:
    20170209212325590982
retcode:
    0
stage-197:
root@salt-master:~# echo $?
0
root@salt-master:~# salt --batch-size 1 --failhard -G 'ec2_roles:stage' cmd.run 'exit 1'

Executing run on ['stage-12']

{'stage-12': {'jid': '20170209212334018054', 'retcode': 1, 'ret': ''}}
ERROR: Minions returned with non-zero exit code.
root@salt-master:~# echo $?
1

Mas quando tento executar um módulo de execução como o seguinte teste:

# mymodule.py
from salt.exceptions import CommandExecutionError

def testfailure():
    raise CommandExecutionError('fail!')

Eu obtenho o seguinte resultado:

root@salt-master:~# salt --batch-size 1 --failhard -G 'ec2_roles:stage' mymodule.testfailure

Executing run on ['stage-12']

jid:
    20170210023059009796
stage-12:
    ERROR: fail!

Executing run on ['stage-13']

jid:
    20170210023059179183
stage-13:
    ERROR: fail!

Executing run on ['stage-197']

jid:
    20170210023059426845
stage-197:
    ERROR: fail!
root@salt-master:~# echo $?
0
    
por c4urself 10.02.2017 / 03:33

3 respostas

2

Não sei ao certo como você lida com erros no seu módulo, mas, de qualquer forma, gostaria de lançar alguma luz sobre isso.

Existe um dicionário damo __context__ . Quando você executa um módulo de execução, o dicionário __context__ persiste em todas as execuções do módulo até que os módulos sejam atualizados. Módulos de estado se comporta de maneira semelhante. O dicionário pode ter uma chave 'retcode' que parece referir-se ao código de retorno que o servo / cliente de sal deve retornar e que você está perdendo.

Eu posso ver isso usado em alguns módulos de execução. Um exemplo do módulo nspawn :

def _make_container_root(name):
    '''
    Make the container root directory
    '''
    path = _root(name)
    if os.path.exists(path):
        __context__['retcode'] = salt.defaults.exitcodes.SALT_BUILD_FAIL
        raise CommandExecutionError(
            'Container {0} already exists'.format(name)
        )
    else:
        try:
            os.makedirs(path)
            return path
        except OSError as exc:
            raise CommandExecutionError(
                'Unable to make container root directory {0}: {1}'
                .format(name, exc)

Agora, as coisas ruins. Eu testei no antigo SaltStack 2015.8.12 e de alguma forma funciona, mas sem usar exceção:

def testfailure():
  __context__['retcode'] = 1

A execução do módulo retorna um código de erro maior que 0 :

 salt my_minion mymodule.testfailure; echo $?
my_minion:
    None
ERROR: Minions returned with non-zero exit code
11

Quando você gera uma exceção, ele pára de funcionar e sempre retorna 0 .

# mymodule.py
from salt.exceptions import CommandExecutionError

def testfailure():
  __context__['retcode'] = 1

  raise CommandExecutionError('fail')

A execução do módulo retorna um código de erro igual a 0 , embora não deva:

salt my_minion mymodule.testfailure; echo $?
my_minion:
    ERROR: fail!
0

Eu também testei na última versão disponível 2016.11.3 e o comportamento é o mesmo. IMO, isso é um bug. Eu relatei aqui .

    
por 10.02.2017 / 13:42
1

Os códigos de saída do AFAIK são um problema geral do Salt. Há um conjunto de tickets em seu rastreador de bugs do Github em relação a esse problema. A melhor maneira de descobrir se os estados de sal foram aplicados com sucesso ou não, é o usado por sal-cozinha . Em poucas palavras, há apenas um simples wrapper em torno do comando salt que gera a saída para as mensagens específicas. O comando grep está seguindo:

grep -e Result.*False -e Data.failed.to.compile -e No.matching.sls.found.for

No seu caso, você também pode adicionar correspondência na string ERROR: . Você provavelmente também precisará inverter o código de saída do grep, pois é 0 quando a correspondência é encontrada. Você poderia fazer isso com um truque simples explicado em esta pergunta . Então, no final, seu comando salt pode se parecer com:

salt <your options go here> | tee grep -q -e Result.*False -e Data.failed.to.compile -e No.matching.sls.found.for -e ERROR: ; test $? -eq 1

Isso mostrará a saída completa do salt, suprimirá a saída do grep e retornará o código de retorno invertido do grep, significando 1 se alguma das mensagens de erro for encontrada e 0 , se não.

    
por 10.02.2017 / 13:03
0

Para alguém que ainda esteja tentando resolver isso, você pode fazer o seguinte:

salt * state.highstate --retcode-passthrough

ou

salt-call * state.highstate --retcode-passthrough

    
por 25.07.2017 / 23:02

Tags