def set_new_weights(dns_name, identifier, lb_dns_name: str, new_record_weights, percentage, rr): action('Setting weights for {dns_name}..', **vars()) did_the_upsert = False for r in rr: if r.type == 'CNAME' and r.name == dns_name: w = new_record_weights[r.identifier] if w: if int(r.weight) != w: r.weight = w rr.add_change_record('UPSERT', r) if identifier == r.identifier: did_the_upsert = True else: rr.add_change_record('DELETE', r) if new_record_weights[identifier] > 0 and not did_the_upsert: change = rr.add_change('CREATE', dns_name, 'CNAME', ttl=20, identifier=identifier, weight=new_record_weights[identifier]) change.add_value(lb_dns_name) if rr.changes: rr.commit() if sum(new_record_weights.values()) == 0: ok(' DISABLED') else: ok() else: ok(' not changed')
def updateAlertDef(yaml_file): """update a single check definition""" data = get_config_data() post = yaml.safe_load(yaml_file) post['last_modified_by'] = data['user'] if 'status' not in post: post['status'] = 'ACTIVE' action('Updating alert definition..') if 'id' not in post: error('"id" missing in definition') return if 'check_definition_id' not in post: error('"check_definition_id" missing in definition') return alert_id = post['id'] r = requests.put(data['url'] + '/alert-definitions/{}'.format(alert_id), json.dumps(post), auth=HTTPBasicAuth(data['user'], data['password']), headers={'Content-Type': 'application/json'}) if r.status_code == 200: ok(get_config_data()["url"].replace("rest/api/v1", "") + "#/alert-details/" + str(r.json()["id"])) else: print(r.text)
def output(output): '''Example for all possible Echo Formats You see the message only, if the Output TEXT ''' with OutputFormat(output): action('This is a ok:') ok() action('This is a ok with message:') ok('all is fine') action('This is a warning:') warning('please check this') with Action('Start with working..') as act: # save_the_world() act.progress() act.progress() act.progress() act.progress() print_table('id name'.split(), [{'id': 1, 'name': 'Test #1'}, {'id': 2, 'name': 'Test #2'}]) info('Only FYI') action('This is a error:') error('this is wrong, please fix') action('This is a fatal error:') fatal_error('this is a fuckup') info('I\'am not printed, the process a dead')
def updateAlertDef(yaml_file): """update a single check definition""" data = get_config_data() alert = yaml.safe_load(yaml_file) alert['last_modified_by'] = data.get('user', 'unknown') if 'status' not in alert: alert['status'] = 'ACTIVE' action('Updating alert definition..') if 'id' not in alert: error('"id" missing in definition') return if 'check_definition_id' not in alert: error('"check_definition_id" missing in definition') return alert_id = alert['id'] r = put('/alert-definitions/{}'.format(alert_id), json.dumps(alert)) if r.status_code != 200: error(r.text) r.raise_for_status() ok(get_base_url(get_config_data()["url"]) + "#/alert-details/" + str(r.json()["id"]))
def group_add(ctx, group_name, user_name): action("Adding user ....") r = put("/groups/{}/member/{}/".format(group_name, user_name)) if r.text == '1': ok() else: error("failed to insert")
def push_entity(ctx, entity): if entity[-4:] == "json" and os.path.exists(entity): with open(entity, 'rb') as file: entity = file.read() data = json.loads(entity.decode()) elif entity[-4:] == 'yaml' and os.path.exists(entity): with open(entity, 'rb') as fd: data = yaml.safe_load(fd) else: data = json.loads(entity) if not isinstance(data, list): data = [data] for e in data: action("creating entity...{}".format(e['id'])) try: entity = json.dumps(e) r = put('/entities/', entity) if r.status_code == 200: ok() else: error() except: error("failed")
def group_remove(ctx, group_name, user_name): action("Removing user ....") r = delete("/groups/{}/member/{}/".format(group_name, user_name)) if r.text == '1': ok() else: error("failed to remove")
def output(output): '''Example for all possible Echo Formats You see the message only, if the Output TEXT ''' with OutputFormat(output): action('This is a ok:') ok() action('This is a ok with message:') ok('all is fine') action('This is a warning:') warning('please check this') with Action('Start with working..') as act: # save_the_world() act.progress() act.progress() act.progress() act.progress() print_table('id name'.split(), [{ 'id': 1, 'name': 'Test #1' }, { 'id': 2, 'name': 'Test #2' }]) info('Only FYI') action('This is a error:') error('this is wrong, please fix') action('This is a fatal error:') fatal_error('this is a fuckup') info('I\'am not printed, the process a dead')
def add_phone(ctx, member_email, phone_nr): action("Adding phone ....") r = put("/groups/{}/phone/{}/".format(member_email, phone_nr)) if r.text == '1': ok() else: error("failed to set phone")
def push_entity(obj, entity): """Push one or more entities""" client = get_client(obj.config) if (entity.endswith('.json') or entity.endswith('.yaml')) and os.path.exists(entity): with open(entity, 'rb') as fd: data = yaml.safe_load(fd) else: data = json.loads(entity) if not isinstance(data, list): data = [data] with Action('Creating new entities ...', nl=True) as act: for e in data: action('Creating entity {} ...'.format(e['id'])) try: client.add_entity(e) ok() except ZmonArgumentError as e: act.error(str(e)) except requests.HTTPError as e: log_http_exception(e, act) except Exception as e: act.error('Failed: {}'.format(str(e)))
def remove_phone(ctx, member_email, phone_nr): action("Removing phone number ....") r = delete("/groups/{}/phone/{}/".format(member_email, phone_nr)) if r.text == '1': ok() else: error("failed to remove phone")
def invoke(op, *args, **kwargs): if op.http_method != 'get': clickclick.action('Invoking..') request = construct_request(op, {}, **kwargs) c = RequestsClient() future = c.request(request) future.result() clickclick.ok()
def switch_active(ctx, group_name, user_name): action("Switching active user ....") r = delete("/groups/{}/active/".format(group_name)) r = put("/groups/{}/active/{}/".format(group_name, user_name)) if r.text == '1': ok() else: error("failed to switch")
def delete_check_definition(check_id): '''Delete an orphan check definition''' action('delete check id {} ...'.format(check_id)) r = delete('/check-definitions/{}'.format(check_id)) if r.status_code == 200: ok() else: error(r.text)
def delete_entity(ctx, entity_id): action("delete entity... {}".format(entity_id)) try: r = delete('/entities/?id={}'.format(urllib.parse.quote_plus(entity_id))) if r.status_code == 200 and r.text == "1": ok() else: error("Delete unsuccessfull") except Exception as ex: error("Exception during delete: " + str(ex))
def get_entity(ctx, entity_id): try: r = get('/entities/{}/'.format(urllib.parse.quote_plus(entity_id))) if r.status_code == 200 and r.text != "": print(dump_yaml(r.json())) else: action("getting entity " + entity_id + "...") error("not found") except Exception as ex: error("Exception during get entity: " + str(ex))
def check_redis_host(host, port=6379): action("Check Redis on {}".format(host)) action("...") try: r = StrictRedis(host, port) workers = r.smembers("zmon:metrics") ok() return r, workers except Exception as e: error(e)
def get_entity(ctx, entity_id): try: r = get('/entities/{}/'.format(urllib.parse.quote_plus(entity_id))) if r.status_code == 200 and r.text != "": print(yaml.safe_dump(r.json(), default_flow_style=False, allow_unicode=True, encoding='utf-8').decode('utf-8')) else: action("getting entity " + entity_id + "...") error("not found") except Exception as ex: error("Exception during get entity: " + str(ex))
def check_schedulers(r, schedulers): for s in schedulers: action('Check scheduler {} .....'.format(s[2:])) try: ts = r.get("zmon:metrics:{}:ts".format(s)) if ts is None: error("No scheduling loop registered ( running/stuck? )") continue delta = int(time.time() - float(ts)) action("... last loop") highlight("{}".format(delta)) action("s ago ...") if delta > 300: error("Last loop more than 300s ago (stuck? restart?)".format(delta)) continue if delta > 180: error("Last loop more than 180s ago (stuck? check logs/watch)".format(delta)) continue action("...") ok() except Exception as e: error(e)
def update(yaml_file): """update a single check definition""" data = get_config_data() post = yaml.safe_load(yaml_file) post['last_modified_by'] = data['user'] if 'status' not in post: post['status'] = 'ACTIVE' action('Updating check definition... ') r = requests.post(data['url'] + '/check-definitions', json.dumps(post), auth=HTTPBasicAuth(data['user'], data['password']), headers={'Content-Type': 'application/json'}) if r.status_code == 200: ok(get_config_data()["url"].replace("rest/api/v1", "") + "#/check-definitions/view/" + str(r.json()["id"])) else: print(r.text)
def set_new_weights(dns_names: list, identifier, lb_dns_name: str, new_record_weights, percentage): action('Setting weights for {dns_names}..', dns_names=', '.join(dns_names)) dns_changes = collections.defaultdict(lambda: []) for idx, dns_name in enumerate(dns_names): domain = dns_name.split('.', 1)[1] hosted_zone = Route53HostedZone.get_by_domain_name(domain) did_the_upsert = False convert_domain_records_to_alias(dns_name) for r in Route53.get_records(name=dns_name): if r.type in [RecordType.CNAME, RecordType.A, RecordType.AAAA]: w = new_record_weights[r.set_identifier] if w: if int(r.weight) != w: r.weight = w dns_changes[hosted_zone.id].append({'Action': 'UPSERT', 'ResourceRecordSet': r.boto_dict}) if identifier == r.set_identifier: did_the_upsert = True else: if dns_changes.get(hosted_zone.id) is None: dns_changes[hosted_zone.id] = [] dns_changes[hosted_zone.id].append({'Action': 'DELETE', 'ResourceRecordSet': r.boto_dict.copy()}) if new_record_weights[identifier] > 0 and not did_the_upsert: if dns_changes.get(hosted_zone.id) is None: dns_changes[hosted_zone.id] = [] elb = ELB.get_by_dns_name(lb_dns_name[idx]) record = Route53Record(name=dns_name, type=RecordType.A, set_identifier=identifier, weight=new_record_weights[identifier], alias_target={"HostedZoneId": elb.hosted_zone.id, "DNSName": lb_dns_name[idx], "EvaluateTargetHealth": False}) dns_changes[hosted_zone.id].append({'Action': 'UPSERT', 'ResourceRecordSet': record.boto_dict}) if dns_changes: route53 = boto3.client('route53') for hosted_zone_id, change in dns_changes.items(): route53.change_resource_record_sets(HostedZoneId=hosted_zone_id, ChangeBatch={'Comment': 'Weight change of {}'.format(hosted_zone_id), 'Changes': change}) if sum(new_record_weights.values()) == 0: ok(' DISABLED') else: ok() else: ok(' not changed')
def create_alert_definition(yaml_file): """Create a single alert definition""" data = get_config_data() alert = yaml.safe_load(yaml_file) alert['last_modified_by'] = data.get('user', 'unknown') if 'status' not in alert: alert['status'] = 'ACTIVE' action('Creating alert definition..') if 'check_definition_id' not in alert: error('"check_definition_id" missing in definition') return r = post('/alert-definitions', json.dumps(alert)) ok(get_base_url(get_config_data()["url"]) + "#/alert-details/" + str(r.json()["id"]))
def update(yaml_file): """update a single check definition""" data = get_config_data() check = yaml.safe_load(yaml_file) check['last_modified_by'] = data.get('user', 'unknown') if 'status' not in check: check['status'] = 'ACTIVE' action('Updating check definition... ') r = post('/check-definitions', json.dumps(check)) if r.status_code != 200: error(r.text) r.raise_for_status() ok(get_base_url(get_config_data()["url"]) + "#/check-definitions/view/" + str(r.json()["id"]))
def set_new_weights(dns_names: list, identifier, lb_dns_name: str, new_record_weights, percentage): action('Setting weights for {dns_names}..', dns_names=', '.join(dns_names)) dns_changes = {} for idx, dns_name in enumerate(dns_names): domain = dns_name.split('.', 1)[1] zone = get_zone(domain) did_the_upsert = False for r in get_records(domain): if r['Type'] == 'CNAME' and r['Name'] == dns_name: w = new_record_weights[r['SetIdentifier']] if w: if int(r['Weight']) != w: r['Weight'] = w if dns_changes.get(zone['Id']) is None: dns_changes[zone['Id']] = [] dns_changes[zone['Id']].append({'Action': 'UPSERT', 'ResourceRecordSet': r}) if identifier == r['SetIdentifier']: did_the_upsert = True else: if dns_changes.get(zone['Id']) is None: dns_changes[zone['Id']] = [] dns_changes[zone['Id']].append({'Action': 'DELETE', 'ResourceRecordSet': r.copy()}) if new_record_weights[identifier] > 0 and not did_the_upsert: if dns_changes.get(zone['Id']) is None: dns_changes[zone['Id']] = [] dns_changes[zone['Id']].append({'Action': 'UPSERT', 'ResourceRecordSet': {'Name': dns_name, 'Type': 'CNAME', 'SetIdentifier': identifier, 'Weight': new_record_weights[identifier], 'TTL': 20, 'ResourceRecords': [{'Value': lb_dns_name[idx]}]}}) if dns_changes: route53 = boto3.client('route53') for hosted_zone_id, change in dns_changes.items(): route53.change_resource_record_sets(HostedZoneId=hosted_zone_id, ChangeBatch={'Comment': 'Weight change of {}'.format(hosted_zone_id), 'Changes': change}) if sum(new_record_weights.values()) == 0: ok(' DISABLED') else: ok() else: ok(' not changed')
def getCheckDefinition(check_id): '''get a single check definition''' r = get('/check-definitions/{}'.format(check_id)) if r.status_code != 200 or r.text == "": action("retrieving check " + str(check_id) + " ...") error("not found") return data = r.json() keys = list(data.keys()) for k in keys: if data[k] is None: del data[k] print(dump_yaml(data))
def update(yaml_file): """update a single check definition""" data = get_config_data() check = yaml.safe_load(yaml_file) check['last_modified_by'] = data.get('user', 'unknown') if 'status' not in check: check['status'] = 'ACTIVE' action('Updating check definition... ') if not check.get('owning_team'): raise click.UsageError('Missing "owning_team" in check definition') validate_check_command(check['command']) r = post('/check-definitions', json.dumps(check)) ok(get_base_url(get_config_data()["url"]) + "#/check-definitions/view/" + str(r.json()["id"]))
def getCheckDefinition(check_id): '''get a single check definition''' r = get('/check-definitions/{}'.format(check_id)) if r.status_code != 200 or r.text == "": action("retrieving check " + str(check_id) + " ...") error("not found") return data = r.json() keys = list(data.keys()) for k in keys: if data[k] is None: del data[k] print(yaml.safe_dump(data, default_flow_style=False, allow_unicode=True, encoding='utf-8').decode('utf-8'))
def dashboard_update(ctx, yaml_file): """Create/Update a single ZMON dashboard""" with open(yaml_file, 'rb') as f: data = yaml.safe_load(f) if 'id' in data: action('Updating dashboard {}..'.format(data.get('id'))) post('/dashboard/{}'.format(data['id']), json.dumps(data)) ok() else: action('Creating new dashboard..') r = post('/dashboard/', json.dumps(data)) data['id'] = int(r.text) with open(yaml_file, 'wb') as f: f.write(dump_yaml(data).encode('utf-8')) ok("new id: {}".format(r.text))
def push_entity(ctx, entity): '''Push one or more entities''' if (entity.endswith('.json') or entity.endswith('.yaml')) and os.path.exists(entity): # JSON is a subset of YAML, so we can use the YAML parser.. with open(entity, 'rb') as fd: data = yaml.safe_load(fd) else: data = json.loads(entity) if not isinstance(data, list): data = [data] for e in data: action("Creating entity {}..".format(e['id'])) try: entity = json.dumps(e) put('/entities/', entity) ok() except: error("failed")
def grafana_update(ctx, yaml_file): """Create/Update a single ZMON dashboard""" with open(yaml_file, 'rb') as f: data = yaml.safe_load(f) title = data.get('dashboard', {}).get('title', None) id = data.get('dashboard', {}).get('id', None) if id is None and title is None: error("id and title missing") if title is None: error("title is missing") action('Updating dashboard title "{}"...'.format(title)) r = post('/grafana2-dashboards', json.dumps(data)) if r.status_code == 200: ok() else: error(r.text)
def test_echo(): action('Action..') ok() action('Action..') error(' some error') action('Action..') with pytest.raises(SystemExit): fatal_error(' some fatal error') # noqa action('Action..') warning(' some warning') info('Some info')
def check_queues(redis): queues = ['zmon:queue:default', 'zmon:queue:snmp', 'zmon:queue:internal', 'zmon:queue:secure'] for q in queues: action('Checking queue length ... {} ...'.format(q)) l = redis.llen(q) action("...") highlight("{}".format(l)) action(" ...") if l < 2000: ok() continue error("to many tasks")
def set_new_weights(dns_names: list, identifier, lb_dns_name: str, new_record_weights: Dict, region: str): action('Setting weights for {dns_names}..', dns_names=', '.join(dns_names)) for idx, dns_name in enumerate(dns_names): domain = dns_name.split('.', 1)[1] hosted_zone = Route53HostedZone.get_by_domain_name(domain) convert_cname_records_to_alias(dns_name) changed = False for stack_name, percentage in new_record_weights.items(): try: stack = CloudFormationStack.get_by_stack_name(stack_name, region=region) except StackNotFound: # The Route53 record doesn't have an associated stack # fallback to the old logic record = None for r in Route53.get_records(name=dns_name): if r.set_identifier == stack_name: record = r break if percentage: record.weight = percentage hosted_zone.upsert( [record], comment="Change weight of {} to {}".format( stack_name, percentage)) else: hosted_zone.delete( [record], comment="Delete {} " "because traffic for it is 0".format(stack_name)) changed = True continue for key, resource in stack.template['Resources'].items(): if (resource['Type'] == ResourceType.route53_record_set and resource['Properties']['Name'] == dns_name): dns_record = stack.template['Resources'][key] break try: dns_record['Properties']['Weight'] = percentage except NameError: raise ELBNotFound(dns_name) try: stack.update() except StackNotUpdated: # make sure we update DNS records which were not updated via CloudFormation record = None for r in Route53.get_records(name=dns_name): if r.set_identifier == stack_name: record = r break if record and record.weight != percentage: record.weight = percentage hosted_zone.upsert( [record], comment="Change weight of {} to {}".format( stack_name, percentage)) changed = True else: changed = True if changed: ok() else: ok(' not changed')
def set_new_weights(dns_names: list, old_record_weights: Dict, new_record_weights: Dict, region: str): action("Setting weights for {dns_names}..", dns_names=", ".join(dns_names)) changed = False updates = {} for idx, dns_name in enumerate(dns_names): domain = dns_name.split(".", 1)[1] hosted_zone = Route53HostedZone.get_by_domain_name(domain) convert_cname_records_to_alias(dns_name) for stack_name, percentage in new_record_weights.items(): if old_record_weights[stack_name] == percentage: # Stack weight will not change continue try: if stack_name not in updates.keys(): stack = CloudFormationStack.get_by_stack_name( stack_name, region=region) else: stack = updates[stack_name]["stack"] except StackNotFound: # The Route53 record doesn't have an associated stack # fallback to the old logic record = None for r in Route53.get_records(name=dns_name): if r.set_identifier == stack_name: record = r break if percentage: record.weight = percentage hosted_zone.upsert( [record], comment="Change weight of {} to {}".format( stack_name, percentage), ) else: hosted_zone.delete( [record], comment="Delete {} " "because traffic for it is 0".format(stack_name), ) changed = True continue for key, resource in stack.template["Resources"].items(): if (resource["Type"] == ResourceType.route53_record_set and resource["Properties"]["Name"] == dns_name): dns_record = stack.template["Resources"][key] break try: dns_record["Properties"]["Weight"] = percentage except NameError: raise ELBNotFound(dns_name) if stack_name not in updates.keys(): update = {"stack": stack, "zones": {}} updates[stack_name] = update else: update = updates[stack_name] if domain not in update["zones"].keys(): records = list() update["zones"][domain] = records else: records = update["zones"][domain] record = None for r in Route53.get_records(name=dns_name): if r.set_identifier == stack_name: record = r break if record and record.weight != percentage: record.weight = percentage records.append({ "record": record, "comment": "Change weight of {} to {}".format(stack_name, percentage), }) for key, update in updates.items(): try: update["stack"].update() except StackNotUpdated: # make sure we update DNS records which were not updated via CloudFormation for domain, records in update["zones"].items(): hosted_zone = Route53HostedZone.get_by_domain_name(domain) for zone_update in records: hosted_zone.upsert([zone_update["record"]], comment=zone_update["comment"]) changed = True else: changed = True if changed: ok() else: ok(" not changed")
def __enter__(self): if self.output == 'text' and not self.printer: action(self.msg) if self.nl: secho('') return self