Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add script which compares two minions #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions utils/compare_minions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env python

import salt.config
import salt.loader

import json
import json_delta

try:
from colorama import Fore, Back, Style, init
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports.

offtop: I prefer to write import like this:

from colorama import (
    Fore, 
    Back, 
    Style, 
    init,
)

— this will bring much nicer git diffs in future

but in python community it's sometimes recommended to write import like this:

from colorama import Back
from colorama import Fore
from colorama import Style
from colorama import init

Copy link
Contributor Author

@bookwar bookwar Jun 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is an "idiomatic" code snippet, which exposes the colorizing interface
I think it is better to keep it in a generic form, rather than customize for particular usage

init()
except ImportError: # fallback so that the imported classes always exist
class ColorFallback():
def __getattr__(self, name):
return ''
Fore = Back = Style = ColorFallback()


def color_diff(diff):
"""Colorize lines in the diff generator object"""

for line in diff:
if line.startswith('+'):
yield Fore.GREEN + line + Fore.RESET
elif line.startswith('-'):
yield Fore.RED + line + Fore.RESET
else:
yield line

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need 2 lines before class def.


class Minion():

default_config = '/opt/{name}/minion'

def __init__(self, name=None, config=None, **salt_params):

if not config:
config = self.default_config.format(name=name)
self.config = config

self.salt_params = salt_params

__opts__ = salt.config.minion_config(self.config)
__grains__ = salt.loader.grains(__opts__)
__opts__['grains'] = __grains__
__utils__ = salt.loader.utils(__opts__)
self.salt = salt.loader.minion_mods(__opts__, utils=__utils__)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it salt or salt_minion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is salt, as the main tool with loaded minion modules


@property
def highstate(self):
return json.loads(json.dumps(self.salt['state.show_highstate'](**self.salt_params)))

@property
def pillar_items(self):
return json.loads(json.dumps(self.salt['pillar.items'](**self.salt_params)))

@property
def grains_items(self):
return json.loads(json.dumps(self.salt['grains.items']()))

def __str__(self):
return json.dumps(
{
"highstate": self.highstate,
"pillar_items": self.pillar_items,
"grains_items": self.grains_items,
},
indent=4
)


def compare_minions(minionA, minionB):
'''Generate colorized unified diff of two minions'''

comparable_properties = [
'highstate',
'pillar_items',
'grains_items',
]

diffs = {}
for key in comparable_properties:
diffs[key] = color_diff(
json_delta.udiff(
getattr(minionA, key),
getattr(minionB, key),
)
)

result = "\n".join(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add output example as this templating is very complex and hard to trace

[
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you may use ( .. ) instead of [ .. ] here

"\n".join(
[key.upper(), "\n".join(value)]
) for key, value in diffs.items()
]
)
return result


Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if __name__ == '__main__': ... otherwise this module will execute following lines on import

if __name__ == "__main__":

minionA = Minion('minionA')
minionB = Minion('minionB')

print compare_minions(minionA, minionB)