I really needed a module like this one and liked the basics of this module but since I needed more functionality than came with this module I decided to extend it.
Attached is a patch that enables modules to in addition to make changes on a switch also check if something is allowed or not in the current environment. Eg. a module making potentially harmful API-calls code check if those are allowed in the current environment by calling environment_allowed('dangerous_api_call_1', 'powerful_api_module', FALSE) - if on a development machine the API-call would then simply silently fail.
The changes can also be found in a development repo of mine at: http://github.com/voxpelli/drupal-environment
Any feedback is welcome - I hope you like these changes.
| Comment | File | Size | Author |
|---|---|---|---|
| #8 | environment.925162-8.patch | 14.38 KB | Grayside |
| #1 | environment_extended2.patch | 14.66 KB | voxpelli |
| environment_extended.patch | 11.63 KB | voxpelli |
Comments
Comment #1
voxpelli commentedNew patch that fixes a bug and makes it possible to require an environment override in the settings.php file (or similar).
Comment #2
ceardach commentedI like the concept. Assigning to Fox to review and commit, since CVS is a PITA for me.
Comment #3
tobiassjosten commentedExcellent feature! It's also working as I'd imagine it's intended, so I'll go ahead and RTBC it.
Comment #4
voxpelli commentedJust a friendly up here - any news on the progress of this issue?
Comment #5
Grayside commentedThat's a huge patch really difficult to review.
I'm not clear on why the environment_allowed() function is useful. How is it more useful than function_exists()?
Also, rather than run
environment_init(), why not just have a no argument environment-switch, or an "environment-validate" command that defaults to the settings.php file's configuration. Checking on every page load might be cheap, but those two bits don't seem necessary since it only needs to run once on the site, and whenever you update the configuration form a certain way.Given that this patch does some thing that are needed, I will run with it. Once it's committed we can revisit issues in a more targeted way.
Comment #6
voxpelli commentedThanks for taking a look at it - here's some comments that might clarify a bit more:
environment_allowed() does something completely different to function_exists() - environment_allowed() is like a dead man's switch which can be used to automatically deactivate functionality and thus prevent the future you or colleagues to accidentally do really stupid stuff when a site has been cloned from one environment to another.
A simple use case would be the sending of e-mails to users - say they have subscribed to notifications to new comments on articles and one of your colleagues doesn't know that. The colleague tests the comments on a local clone of a production site and hasn't deactivated e-mail in his local php. When he posts a comment the users gets e-mails when they should have received nothing. By checking environment_allowed() prior to sending the mails it would've been possible to stop the mails from being sent.
The idea behind environment_init() is that the environment switch should happen automatically as soon as a move between environments has been detected. It should perhaps be even more aggressive than I did in my patch and actually redirect and die after the switch to ensure that the switch takes full effect. This is to ensure that no evil code is run by mistake because the switch hadn't run.
When using a dump of a production database it will include a variable indicating the environment. If you've defined an override in your local settings.php it will be checked against that and if they don't match then a switch of the environment will happen automatically. You shouldn't be able to run the site on a different environment without doing a switch - it should be enforced and as foolproof as possible.
Comment #7
Grayside commentedOkay, that is helpful clarification of environment_allowed().
I disagree with environment_init(). After thinking further about it, I feel that the efficiency gain of skipping a line in a deployment script is not as great as the risk of a corner case botch in a variables table leading immediately to changing your environment status.
Strongly enough that despite the fact that I am already rolling patches against your patch, I will mark this as needs work. Hopefully ceardach or hefox can put two cents in.
Looking at the code, I see there is a hook_environments() for declaring additional environments. Why does this pull on an environment_definitions variable that is nowhere else set?
Comment #8
Grayside commentedAttached patch removes the init stuff and does some small bits of cleanup, the most daring of which is in admin.inc.
My intent is to get this committed so we have the expanded functionality as a baseline to proceed with more cool stuff in the next couple days. Ceardach has asked me to run with some of this stuff, so I will commit this tomorrow, hopefully after someone else RTBC's.
Comment #9
voxpelli commentedAs I said - environment_init() isn't about efficiency - it's about fool proofing. To have a working dead mans switch functionality we need to switch environments as soon as we notice that something has moved.
I don't see how this can botch anything - and even if it would couldn't we make it optional instead of removing it? Would love it if we can solve this issue prior to committing anything :)
The environment_definitions variable can be used to add additional local environments that has different settings than one of the predefined ones.
Comment #10
Grayside commentedRe: environment_init()
I really don't like the idea of an automated environment change, in the same way I wouldn't like it if the updatedb ran automatically if it detected updates were needed. I wouldn't mind seeing this place a message in the Status page, and possibly even a drupal_set_message() reminder. Another reasonable possibility is micro-module that implements hook_init() as you have it.
From my perspective I'd prefer to get the other stuff committed ASAP as it's generally a big improvement. a tie-breaking vote would be great here.
Re: environment_states
But without a UI, what's the point of it?
I definitely see the potential for making a UI around environment states. I'm just unclear about the benefit of both a UI and a hook.
Comment #11
voxpelli commentedI understand your concern and that it is quite a bad flow for what you intend to use this module for - which is something similar to hook_update_N() - but it's still quite a good flow for what I intend to use it for - fool proofing sites from myself and dangerous colleagues (no offense all colleagues).
Could we make the init hook optional and make the default to not have it activated? That would work for me - would you find that okay as well?
Comment #12
Grayside commentedMy paranoic side says I should push for an environment_enforced.module. Then the checkbox option would be on admin/build/modules. Is that close enough?
Comment #13
Grayside commentedPatch #8 committed as is. Let's continue talking about the enforced state stuff.
Comment #14
voxpelli commentedKind of ironic that you're being paranoid about a mechanism meant to protect against paranoia ;) The checkbox can never cause any damage - even for your use case it wont cause any damage, its just that it works better when not enabled.
For my use case though: It does _not_ work without the init function - so could you please try and understand my use case or tell me if I've misunderstood yours? :) Why is it more important that your use case is supported by environment.module than that mine is?
Comment #15
Grayside commentedThe main purpose of the Environment module is not to validate that the current state is enforced, it's to transition between states when you need different site behaviors. My resistance is the same reason why automatic running of updatedb isn't even an option in Core--because if something goes wrong, you have something between a bad security breach, data corruption, and site failure.
I am not absolutely against it, and I understand the value of the functionality you describe. Puppet-like behavior certainly has a value, and one I have only started to think about in the context of Drupal since you have pointed it out.
What I'm trying to evaluate now is whether it is acceptable for it to be in a submodule, so the edge case that ruins someone's day has that slight extra defense around it.
Comment #16
Grayside commentedCan we step back a moment and look at the root goal here? Are you trying to block someone changing the environment on a site controlled by settings.php? Because we could simply handle that with validation in the UI's related to environment switching.
We can also do something like this:
Now when we grab the current environment, settings.php always has a chance to override it.
Comment #17
voxpelli commentedWhat I'm trying to do is to force an environment independently of the database and to detect when a database moves between environments - so almost what you're saying.
I thought about your solution as well - but didn't like the fact that the environment can change without the switch mechanism being executed. But hook_requirements() can perhaps, as you somewhere suggested, be used to highlight such inconsistencies by checking if the 'environment_override' variable doesn't match the 'environment' variable and show a warning that the switch scripts should be executed.
Such a mechanism would be more in line with core.
Comment #18
Grayside commentedSo we have:
1. A hook_requirements() implementation that shows a warning when there is an environment state mismatch.
2. A warning that links to a confirmation page to run the switch.
3. An environment_enforcement submodule that simply automates this.
Comment #19
voxpelli commentedSounds good
Comment #20
Grayside commentedLet's go ahead and separate these out.