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

Implement an Admin Flag model and some Emergency Circuit breakers #2967

Merged
merged 10 commits into from
Feb 18, 2018

Conversation

ewdurbin
Copy link
Member

Allows us to query any flag and it will default to False until created and enabled.

"User Registration Temporarily Disabled",
queue="error",
)
raise HTTPForbidden()
Copy link
Member

Choose a reason for hiding this comment

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

Could be wrong here but I'm not sure the flashed message will appear on the 403 page.

Copy link
Member Author

Choose a reason for hiding this comment

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

hrm... yeah. good catch.

Copy link
Member Author

Choose a reason for hiding this comment

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

We certainly need to message correctly to users what's up whenever we use these. I'm going to see what options we have.

Copy link
Member

Choose a reason for hiding this comment

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

Could just redirect to a page that shows the flashed messages (like the index).

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed!

raise _exc_with_message(
HTTPForbidden,
("New Project Registration Temporarily Disabled "
"See https://pypi.org/help#admin-intervention for details"),
Copy link
Member

Choose a reason for hiding this comment

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

Maybe use a request.route_path for the URL here instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

probably a good refactor for all of our /help down the line.

Copy link
Member

@di di left a comment

Choose a reason for hiding this comment

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

LGTM aside from some very small nits!

@ewdurbin ewdurbin changed the title AdminFlag: Implement an Admin Flag model Implement an Admin Flag model and some Emergency Circuit breakers Feb 18, 2018
@@ -215,6 +216,14 @@ def register(request, _form_class=RegistrationForm):
if request.authenticated_userid is not None:
return HTTPSeeOther("/")

if AdminFlag().is_enabled(request.db, 'disallow-new-user-registration'):
Copy link
Member

Choose a reason for hiding this comment

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

You don't need to instantiate AdminFlag here, should just be AdminFlag.is_enabled(...). Same with the other callsite.

Copy link
Member Author

Choose a reason for hiding this comment

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

d'oh missed that in factoring to a classmethod. thanks.



def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
Copy link
Member

Choose a reason for hiding this comment

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

Not a big deal, but I normally remove these lines, at least as a marker that I looked at the migration and it's doing the right thing.

enabled = Column(Boolean)

@classmethod
def is_enabled(cls, session, flag_name):
Copy link
Member

Choose a reason for hiding this comment

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

This should probably either be a static method, or it should use cls in the body instead of AdminFlag.

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, also missed while factoring to a classmethod. do you have a preference between classmethod or static method for this?

Copy link
Member

Choose a reason for hiding this comment

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

I don't really. I'd maybe use a classmethod just to make inheritance work... but I don't think that really matters since we're never going to use inheritance here anyways.


id = Column(Text, primary_key=True, nullable=False)
description = Column(Text, nullable=False)
enabled = Column(Boolean)
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason to allow this to nullable? What state does that represent? AFAIK there is only two states for a flag, either on or off?

Copy link
Member Author

Choose a reason for hiding this comment

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

nope, clear oversight :)

flag = (session.query(AdminFlag)
.filter(AdminFlag.id == flag_name)
.first())
if flag is None:
Copy link
Member

Choose a reason for hiding this comment

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

I'm torn on this, on one hand it's nice that by surviving a flag not existing in the database, that we're able to handle things like the code running prior to migrations having being ran. However I think that generally code can require a migration being ran-- but migrations have to be compatible with the previous iteration of Warehouse right?

In that case I think I would suggest making it a hard error to not have the flag exist in the database, and prepopulate the database in the migration with any new admin flags. That also leads the way to an eventual admin interface for these, where the admin interface itself doesn't allow creating new admin flags (since they require code support, and getting the ID correct is important) but does allow toggling the flag on/off.It also means there is a single place we can see all of the admin flags (in the DB).

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd certainly rather failsafe than make it a hard error if a flag isn't available. Consider the case where a release is being canaried and has optional migrations or works around those in some fashion.

But, I did add the flags we're using into the migration, as indeed it significantly reduces the complexity the Admin interface implementation.

@ewdurbin
Copy link
Member Author

screen shot 2018-02-18 at 12 37 10 pm

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.

4 participants