Skip to content

Complex Mapping feature (LIGHTLY TESTED, NEEDS REVIEW)#31

Merged
phil-levy merged 18 commits into
adobe-apiplatform:masterfrom
metasemi:morr-cxmap
Mar 1, 2017
Merged

Complex Mapping feature (LIGHTLY TESTED, NEEDS REVIEW)#31
phil-levy merged 18 commits into
adobe-apiplatform:masterfrom
metasemi:morr-cxmap

Conversation

@metasemi

Copy link
Copy Markdown

No description provided.

Comment thread user_sync/config.py
for extension_config in extensions_config.iter_dict_configs():
context = extension_config.get_string('context')
if context == 'per-user':
if (after_mapping_hook == None):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this test needed/correct? Looks like after_mapping_hook set to None a few lines up.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This is testing for multiple per-user extensions; see the matching else.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Got it. Missed the loop.

@adobeDan adobeDan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is almost ready to be merged, and most of my suggested changes are not critical, but a few at least need to be considered carefully before we merge.

Comment thread user_sync/config.py
after_mapping_hook = None
extended_attributes = None
extensions_config = self.main_config.get_list_config('extensions', True)
if (extensions_config != None):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In line 202 you use the correct construction if group is None but here you are not: it should be if extensions_config is not None. I suspect you are being influenced by the existing code style (see line 307), but this code is materially worse in performance because it forces a type check.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I used the equality when in the midst of a block of code that was already using it; otherwise I did what you're calling the right way. Should be addressed globally.

Comment thread user_sync/config.py
organization_name = user_sync.rules.OWNING_ORGANIZATION_NAME
if (len(group_name) == 0):
group = self.create_dashboard_group(dashboard_group)
if (group is None):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ouch! Parentheses around if conditions are not only unnecessary in Python, they are actively discouraged. I assume you are doing this because the rest of the Ensemble code does this, but yuck! We really should fix all this code. Parentheses in Python should be used entirely for precedence and readability; nothing else.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, following the style of the codebase...

Comment thread user_sync/config.py
if context == 'per-user':
if (after_mapping_hook == None):
after_mapping_hook_text = extension_config.get_string('after_mapping_hook')
if (after_mapping_hook_text is not None):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This kind of deeply nested if (the three tests including this one) where the else parts are errors make the code really hard to follow. You should do the "go" thing here: invert the test and have the if part log the warning and skip the rest of the code.

if context != 'per-user':
    self.logger.warning("Unrecognized extension context '%s' ignored", context)
    continue
...

Also consider breaking this loop or body of this loop out as a helper function.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Leaving this for now, but agree with you. Will fix if I have time.

Comment thread user_sync/config.py
# thoroughly tested.
#
for extended_dashboard_group in extension_config.get_list('extended_dashboard_groups'):
group = self.create_dashboard_group(extended_dashboard_group)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I can see from the code later on that create_dashboard_group ignores the group if it already exists as a dashboard group. This means you are guarding against people specifying groups in their extended_dashboard_groups that are already groups in the mapping, which seems like it would be a common (and forgiveable) mistake. A comment to that effect would be useful here (and also in the docs).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Actually create_dashboard_group did not behave that way. But it does now :)

Comment thread user_sync/connector/directory_csv.py Outdated
:rtype (bool, iterable(dict))
'''
if (extended_attributes is not None):
self.logger.warning("CSV directory connector doesn't support extended_attributes; ignored")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Really? Seems like it would be really really easy for the CSV connector to support extended attributes, since you could just add them as column headers. And this seems like it would be a really, really handy way to test extended logic on just a few people...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Doesn't really make sense for csv to have extended attrs because all csv attrs are always included in the data. No need to ask it to include more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Right, that's exactly my point 👍 . We are warning the user that the CSV connector doesn't support extended attributes but in fact I believe the CSV connector already supports extended attributes without our doing any coding!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So I think the action here is to silently ignore the extended attrs list. Just like with AD, if there is no such attr, it just won't show up.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Right, so Phil and I agree: just remove this test. The CSV directory connector does support extended attributes, as far as we know. Have you verified otherwise, Mike?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Great, done.

Comment thread user_sync/rules.py Outdated
self.after_mapping_hook_scope['target_attributes'].pop('source_attributes', None)

# invoke the customer's hook code
# [TODO morr 2017-02-27: Not putting any guardrails around the customer's code, which is treated as

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You're giving them a confined scope; there's nothing really they can do except crash us or hang us. And there's no good way to guard against that :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What about exceptions flying out?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Right, that's the crash case. I don't think we should guard against that, because we can't continue, and it's pointless for us to catch, log, and rethrow.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Agreed, removing the comment. Similarly we don't catch errors compiling the hook code, and the resulting behavior is excellent.

Comment thread user_sync/rules.py
else:
self.logger.error('Target dashboard group %s is not known; ignored', target_group_qualified_name)

self.logger.info('Total directory users after filtering: %d', len(filtered_directory_user_by_user_key))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there some corresponding log of Total directory users before filtering? If not, why not, and if so, why isn't this statement next to it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This was not changed by me, but fwiw this is not confusing in the actual log, modulo the fact that the term "filtering" is used in multiple ways - the --users way and the all_users_filter way. (This is talking about the former.) Anyway I'm not doing anything here.

Comment thread user_sync/rules.py Outdated



def log_after_mapping_hook_scope(self, before_call):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ouch! A boolean variable named before_call, so the call has True or False in it? That's really opaque! Either use keyword variables before_call=False, after_call=False and have the caller specify one of them (and err if caller doesn't), or have a variable context which has a string value which must be before_call or after_call (and is an error otherwise).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Agree with your complaint, though I can't say I'm crazy about either proposed fix. Leaving alone for now.

Comment thread user_sync/rules.py Outdated
# invoke the customer's hook code
# [TODO morr 2017-02-27: Not putting any guardrails around the customer's code, which is treated as
# friendly. Is there anything we should be doing?
self.log_after_mapping_hook_scope(True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ouch! How opaque is this! See comment at line 683.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Leaving alone for now.

Comment thread user_sync/rules.py
def log_after_mapping_hook_scope(self, before_call):
when = 'before' if before_call else 'after'
if (before_call):
self.logger.debug('.')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what is this about? are you trying to get a separator line in the log? I bet we could be a lot clearer than a simple period.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It's pretty great the way it is. What would you suggest? :)

@metasemi
metasemi requested review from adobeDan and phil-levy March 1, 2017 00:46
@phil-levy
phil-levy merged commit b0fa845 into adobe-apiplatform:master Mar 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants