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

[Uptime] Update TLS settings #64111

Merged
merged 12 commits into from
Apr 24, 2020

Conversation

justinkambic
Copy link
Contributor

@justinkambic justinkambic commented Apr 21, 2020

Summary

We had previously made changes that added some fields to the Settings page in the Uptime solution. The needs for these fields have changed, so this patch renames them. Additional refactoring went into the way the form components receive input and interact with our state store.

Testing

Navigate to the Uptime settings page and modify the values for each field. Make sure that the values you provide are persisted.

Also, log in as a user who has readonly access in the current space, and ensure they're unable to edit the values on the page. No changes were made to the API side of this feature, so you shouldn't need to check access restrictions, but you can test that as well to ensure it's working if you choose.

Refactoring summary

Constant values

Previously, we had some default values that were hosted in our runtime_types directory. I don't think this is the place to put those values, because we're not doing that anywhere else in the app, and we're referencing those values from many places. I moved them to a new file in the constants folder, and I think that will be a good place to centrally locate all our default settings values as that feature grows.

State management

The settings form had an optional field for its state in the store. Given that the server will return the default values discussed above, we should feel comfortable referencing the default values in our store's bootstrap code as well. I made that field required and referenced the default values. Doing this means we'll never not have values for the settings in practice, unless something strange is done to the saved objects outside the scope of this code.

Because we're guaranteeing settings values now, we can remove a lot of branching code in the settings page.

Additionally, I adopted the translation pattern we've discussed previously offline and extracted all the i18n references from the settings page and added them to a dedicated file that the other pages can eventually reference as well.

We're spending a lot of energy thinking and talking about shortening value names like dateRangeStart. Given that we're already nesting cert settings values in a dedicated object, I gave the values themselves short names.

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@justinkambic justinkambic added release_note:enhancement v8.0.0 Team:Uptime - DEPRECATED Synthetics & RUM sub-team of Application Observability v7.8.0 labels Apr 21, 2020
@justinkambic justinkambic self-assigned this Apr 21, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/uptime (Team:uptime)

Copy link
Contributor

@andrewvc andrewvc left a comment

Choose a reason for hiding this comment

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

Left a comment on the move from the optional settings? value in the store to settings. I haven't reviewed the rest yet. This is a meaty topic worthy of discussion.

loadError?: Error;
saveError?: Error;
loading: boolean;
}

const initialState: DynamicSettingsState = {
settings: DYNAMIC_SETTINGS_DEFAULTS,
Copy link
Contributor

@andrewvc andrewvc Apr 22, 2020

Choose a reason for hiding this comment

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

This feels cleaner for the settings page in some ways because it reduces LoC, but unless I'm missing something carries hidden complexity that will be paid during the construction of other features.

Before this change one could simply check !!settings to see if they had a reasonably recent value to use. Now, however, one must reason about the state of loadError, saveError and loading, otherwise you might display to the user the default value, which could be terribly incorrect. The settings page itself must reason about all these variables but there's no escaping the fact that the settings page's concern is the current value of these items and their state transitions. Paying that cost in the code of the settings component is expected. Other consumers of settings don't care about anything other than that a fairly recent value of settings was loaded. What they don't want, however, is a fake default value. That could do some damage.

Imagine we use settings on another page, the alert flyout for instance. Before this change we would only need to check !!settings. One might think that now one needs to check !loading instead, however, is that the right thing? What if a reload was triggered but the values haven't changed. Well, we don't know, now we have to subscribe to an update. What if the load fails? Now we also need to check loadError, so now we need to check !loading && !loadError. What if the load failed, but the settings values are still current enough? Do we now do !loading && !loadError && settings != DEFAULT_SETTINGS, which will tell us if it loaded at least once successfully, but only in the case where the user changed the settings? This would be an easy bug to miss in a code review, and it's more thinking. If later we change any of these variables for any reason then we need to hunt down this logic all over the app, or use a helper function. It'd be much easier to just use the optional settings?.

TL;DR Reasoning about the lifecycle of settings carefully on the settings page makes sense, that's that page's job. Everywhere else it should be as simple as possible. The settings object is truly an optional, we can't hide that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Point taken about the risk of displaying incorrect values and the associated awfulness. I had initially thought about compromising by making all the settings values Partial, but we discussed this a bit offline and decided that someone could add a Type value in the future, which would open us up to the same problem. It's better to make this optional at the root and add branching code where it's necessary.

I think the true representation is an optional Partial type, where all the fields are also optional. We could conceivably have some valid fields and others invalid.

I'll make an edit and ping you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've made the settings field optional again.

Copy link
Contributor

@shahzad31 shahzad31 left a comment

Choose a reason for hiding this comment

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

Thank you for taking care of it, just few suggestion and it will be good to go.

export const DYNAMIC_SETTINGS_DEFAULTS: DynamicSettings = {
heartbeatIndices: 'heartbeat-8*',
certificatesThresholds: {
expiration: 7,
Copy link
Contributor

Choose a reason for hiding this comment

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

i think this should be 30 days be default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in d0246a7.

export const CertificatesStatesThresholdType = t.interface({
warningState: t.number,
errorState: t.number,
export const CertificatesStatesThresholdType = t.partial({
Copy link
Contributor

Choose a reason for hiding this comment

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

i think this shouldn't be partial.

Copy link
Contributor

Choose a reason for hiding this comment

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

would it make sense just to rename it CertStateThresholds WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

id="xpack.uptime.sourceConfiguration.stateThresholds"
defaultMessage="Expiration State Thresholds"
id="xpack.uptime.sourceConfiguration.expirationThreshold"
defaultMessage="Expiration/Age Thresholds"
Copy link
Contributor

Choose a reason for hiding this comment

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

we should also add that text here which got updated in ACs "Change the threshold for displaying and alerting on certificate errors. Note, this will affect any configured alerts"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added this copy in 0ddd97b, modified the punctuation a bit in a1fdf46.

@@ -63,7 +62,7 @@ export const IndicesForm: React.FC<SettingsFormProps> = ({
id="xpack.uptime.sourceConfiguration.heartbeatIndicesDefaultValue"
defaultMessage="The default value is {defaultValue}"
values={{
defaultValue: <EuiCode>{defaultDynamicSettings.heartbeatIndices}</EuiCode>,
defaultValue: <EuiCode>{dss.settings.heartbeatIndices}</EuiCode>,
Copy link
Contributor

Choose a reason for hiding this comment

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

This change will display the current value? default value should come from constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right you are, we don't want that to change!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is using defaults again now.

const errorStateErr = certificatesThresholds?.errorState ? null : blankStr;
const warningStateErr = certificatesThresholds?.warningState ? null : blankStr;
const errorStateErr = certificatesThresholds?.expiration ? null : blankStr;
const warningStateErr = certificatesThresholds?.age ? null : blankStr;
Copy link
Contributor

Choose a reason for hiding this comment

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

can you also rename var name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I realized we needed to improve this, so I added a type and renamed the var usage in 59e60e8.

}
};
const onChangeFormField: OnFieldChangeType = changedField =>
setFormFields(Object.assign({ ...merge(formFields, changedField) }));
Copy link
Contributor

Choose a reason for hiding this comment

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

We are using merge bcoz Object.assign doesn't take of nested merging, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've gotten rid of merge altogether because it isn't pure and it was editing the state var. I'm wondering if settings shouldn't just be a flat object to avoid recursive concerns when editing slices of it.

Copy link
Contributor

Choose a reason for hiding this comment

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

yes i think having a right data structure is important, i do agree, having nested have made a lot of complexity. if you think, it's worth an effort, go ahead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll make a follow-up issue.

We have other more important stuff we need to review and it's not worth holding that up for more work in this patch. We don't have any further settings changes planned for the time being, so this complexity shouldn't increase any more than what it is right now until we can get to it. It should be a light patch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

[String(setDynamicSettings)]: state => ({
...state,
loading: true,
}),
[String(setDynamicSettingsSuccess)]: (state, action: Action<DynamicSettings>) => ({
...state,
Copy link
Contributor

Choose a reason for hiding this comment

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

it's not necessary to destructure prev state to return new state, if you know what new state can be in absolute terms.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

++ I removed these additions in 8412951

I think initially I thought some state-related issue was happening because of the lack of spread on unreferenced state params, and then never removed them after the fact.

const errorInput = await testSubjects.find('error-state-threshold-input-loaded', 5000);
const warningInput = await testSubjects.find('warning-state-threshold-input-loaded', 5000);
const errorInput = await testSubjects.find('expiration-threshold-input-loaded', 5000);
const warningInput = await testSubjects.find('age-threshold-input-loaded', 5000);
Copy link
Contributor

Choose a reason for hiding this comment

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

var name rename plz :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed in f7678b6

@justinkambic
Copy link
Contributor Author

@shahzad31 I think I've addressed your feedback, should be ok for a second look when you have time.

Copy link
Contributor

@shahzad31 shahzad31 left a comment

Choose a reason for hiding this comment

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

LGTM !!

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@justinkambic justinkambic merged commit e918c43 into elastic:master Apr 24, 2020
justinkambic added a commit to justinkambic/kibana that referenced this pull request Apr 24, 2020
* Refactor settings form event handling and modify certs fields.

* Fix/improve broken types/unit/integration/api tests.

* Modify default expiration threshold.

* Rename test vars.

* Implement PR feedback.

* Refresh snapshots, fix broken tests/types.

* Remove unnecessary state spreading.

* Add type for settings field errors.

* Refresh test snapshots.

* Improve punctuation.
jloleysens added a commit to jloleysens/kibana that referenced this pull request Apr 27, 2020
…bana into ingest-node-pipeline/open-flyout-create-edit

* 'feature/ingest-node-pipelines' of github.com:elastic/kibana: (116 commits)
  [Ingest Node Pipelines] More lenient treatment of on-failure value (elastic#64411)
  Report Deletion via UI- functional test (elastic#64031)
  Bump handlebars dependency from 4.5.3 to 4.7.6 (elastic#64402)
  [Uptime] Update TLS settings (elastic#64111)
  [alerting] removes usage of any throughout Alerting Services code (elastic#64161)
  [CANVAS] Moves notify to a canvas service (elastic#63268)
  [Canvas] Misc NP Stuff (elastic#63703)
  update apm index pattern (elastic#64232)
  Task/hostlist pagination (elastic#63722)
  [NP] Vega migration (elastic#63849)
  Move ensureDefaultIndexPattern into data plugin (elastic#63100)
  [Fleet] Fix agent status count to not include unenrolled agents (elastic#64106)
  Migrate graph_workspace saved object registration to Kibana platform (elastic#64157)
  Index pattern management UI -> TypeScript and New Platform Ready (edit_index_pattern) (elastic#64184)
  [ML] EuiDataGrid ml/transform components. (elastic#63447)
  [ML] Moving to kibana capabilities (elastic#64057)
  Move input_control_vis into NP (elastic#63333)
  remove reference to local application service in graph (elastic#64288)
  KQL removes leading zero and breaks query (elastic#62748)
  [FieldFormats] Cleanup: rename IFieldFormatType -> FieldFormatInstanceType (elastic#64193)
  ...
justinkambic added a commit that referenced this pull request Apr 27, 2020
* [Uptime] Update TLS settings (#64111)

* Refactor settings form event handling and modify certs fields.

* Fix/improve broken types/unit/integration/api tests.

* Modify default expiration threshold.

* Rename test vars.

* Implement PR feedback.

* Refresh snapshots, fix broken tests/types.

* Remove unnecessary state spreading.

* Add type for settings field errors.

* Refresh test snapshots.

* Improve punctuation.

* Change default index pattern from 8.x to 7.x value.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
@justinkambic
Copy link
Contributor Author

Backported to:

7.x/7.8.0 0214129
#64469

@justinkambic justinkambic deleted the uptime_tls-settings branch April 27, 2020 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release_note:enhancement Team:Uptime - DEPRECATED Synthetics & RUM sub-team of Application Observability v7.8.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants