foreman_rh_cloud 4.0.31 → 5.0.31

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/inventory_upload/report_actions.rb +1 -1
  3. data/app/controllers/foreman_inventory_upload/reports_controller.rb +1 -1
  4. data/app/controllers/insights_cloud/hits_controller.rb +1 -1
  5. data/app/models/insights_hit.rb +4 -0
  6. data/app/models/setting/rh_cloud.rb +0 -1
  7. data/app/models/task_output_line.rb +2 -0
  8. data/app/models/task_output_status.rb +2 -0
  9. data/config/Gemfile.lock.gh_test +204 -168
  10. data/config/package-lock.json.gh_test +14336 -7973
  11. data/config/package-lock.json.plugin +10551 -7500
  12. data/config/routes.rb +1 -1
  13. data/db/migrate/20211027000001_create_task_output.foreman_rh_cloud.rb +18 -0
  14. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +11 -7
  15. data/lib/foreman_inventory_upload/async/generate_report_job.rb +24 -12
  16. data/lib/foreman_inventory_upload/async/progress_output.rb +5 -28
  17. data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +20 -5
  18. data/lib/foreman_inventory_upload/async/shell_process.rb +17 -4
  19. data/lib/foreman_inventory_upload/async/upload_report_job.rb +22 -13
  20. data/lib/foreman_rh_cloud/engine.rb +12 -11
  21. data/lib/foreman_rh_cloud/version.rb +1 -1
  22. data/lib/insights_cloud/async/insights_scheduled_sync.rb +11 -7
  23. data/lib/tasks/rh_cloud_inventory.rake +2 -2
  24. data/package.json +7 -12
  25. data/test/controllers/insights_sync/settings_controller_test.rb +2 -2
  26. data/test/controllers/uploads_settings_controller_test.rb +2 -2
  27. data/test/jobs/insights_full_sync_test.rb +2 -2
  28. data/test/jobs/insights_resolutions_sync_test.rb +1 -1
  29. data/test/jobs/insights_rules_sync_test.rb +2 -2
  30. data/test/jobs/inventory_full_sync_test.rb +3 -3
  31. data/test/jobs/inventory_hosts_sync_test.rb +1 -1
  32. data/test/jobs/inventory_scheduled_sync_test.rb +2 -2
  33. data/test/jobs/inventory_self_host_sync_test.rb +1 -1
  34. data/test/jobs/upload_report_job_test.rb +6 -4
  35. data/test/test_plugin_helper.rb +0 -2
  36. data/test/unit/rh_cloud_http_proxy_test.rb +1 -1
  37. data/test/unit/rh_cloud_permissions_test.rb +14 -0
  38. data/test/unit/services/foreman_rh_cloud/branch_info_test.rb +1 -1
  39. data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +1 -1
  40. data/test/unit/shell_process_job_test.rb +3 -1
  41. data/test/unit/slice_generator_test.rb +3 -3
  42. data/test/unit/tags_generator_test.rb +2 -2
  43. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListActions.js +1 -1
  44. data/webpack/ForemanInventoryUpload/Components/AccountList/accountList.scss +8 -0
  45. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +3 -3
  46. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/index.js +0 -2
  47. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.scss +17 -4
  48. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +29 -17
  49. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +58 -47
  50. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +12 -10
  51. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +10 -10
  52. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonActions.js +1 -1
  53. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +1 -1
  54. data/webpack/ForemanRhCloudFills.js +14 -0
  55. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettingsActions.js +1 -1
  56. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +22 -6
  57. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableActions.js +23 -16
  58. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +49 -2
  59. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableHelpers.js +31 -14
  60. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +19 -2
  61. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTableActions.test.js.snap +0 -1
  62. data/webpack/InsightsCloudSync/Components/InsightsTable/table.scss +11 -13
  63. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.scss +0 -14
  64. data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +13 -0
  65. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/NoTokenEmptyState.test.js.snap +24 -13
  66. data/webpack/InsightsCloudSync/InsightsCloudSyncHelpers.js +8 -0
  67. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +1 -1
  68. data/webpack/InsightsHostDetailsTab/InsightsTab.scss +4 -0
  69. data/webpack/InsightsHostDetailsTab/InsightsTabActions.js +1 -1
  70. data/webpack/InsightsHostDetailsTab/InsightsTabConstants.js +75 -0
  71. data/webpack/InsightsHostDetailsTab/InsightsTotalRiskChart.js +147 -0
  72. data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +103 -0
  73. data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js +1 -0
  74. data/webpack/__mocks__/foremanReact/components/Head.js +11 -0
  75. data/webpack/__mocks__/foremanReact/{redux/actions/toasts.js → components/ToastsList/index.js} +0 -0
  76. data/webpack/common/DropdownToggle.js +24 -0
  77. data/webpack/common/ForemanTasks/ForemanTasksActions.js +1 -1
  78. data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +1 -0
  79. metadata +11 -3
  80. data/webpack/__mocks__/foremanReact/components/Layout/LayoutSelectors.js +0 -1
@@ -0,0 +1,147 @@
1
+ import React, { useEffect, useState, useMemo } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useDispatch } from 'react-redux';
4
+ import { push } from 'connected-react-router';
5
+ import { useHistory } from 'react-router-dom';
6
+ import { DropdownItem, Bullseye, Title } from '@patternfly/react-core';
7
+ import { ChartDonut, ChartLegend, ChartLabel } from '@patternfly/react-charts';
8
+ import { STATUS } from 'foremanReact/constants';
9
+ import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
10
+ import CardTemplate from 'foremanReact/components/HostDetails/Templates/CardItem/CardTemplate';
11
+ import { translate as __ } from 'foremanReact/common/I18n';
12
+ import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
13
+ import { insightsCloudUrl } from '../InsightsCloudSync/InsightsCloudSyncHelpers';
14
+ import { getInitialRisks, theme } from './InsightsTabConstants';
15
+
16
+ const InsightsTotalRiskCard = ({ hostDetails: { id } }) => {
17
+ const [totalRisks, setTotalRisks] = useState(getInitialRisks());
18
+ const hashHistory = useHistory();
19
+ const dispatch = useDispatch();
20
+ const API_KEY = `HOST_${id}_RECOMMENDATIONS`;
21
+ const API_OPTIONS = useMemo(() => ({ key: API_KEY }), [API_KEY]);
22
+ const {
23
+ status = STATUS.PENDING,
24
+ response: { hits = [] },
25
+ } = useAPI('get', insightsCloudUrl(`hits/${id}`), API_OPTIONS);
26
+
27
+ useEffect(() => {
28
+ if (status === STATUS.RESOLVED) {
29
+ const risks = getInitialRisks();
30
+ hits.forEach(({ total_risk: risk }) => {
31
+ risks[risk].value += 1;
32
+ });
33
+ risks.total = hits.length;
34
+ setTotalRisks(risks);
35
+ }
36
+ }, [hits, status]);
37
+
38
+ const onChartClick = (evt, { index }) => {
39
+ hashHistory.push(`/Insights`);
40
+ dispatch(
41
+ push({
42
+ search: `search=total_risk+%3D+${index + 1}`,
43
+ })
44
+ );
45
+ };
46
+
47
+ const onChartHover = (evt, { index }) => [
48
+ {
49
+ mutation: ({ style }) => ({
50
+ style: { ...style, fill: totalRisks[index + 1]?.hoverFill },
51
+ }),
52
+ },
53
+ ];
54
+
55
+ const { 1: low, 2: moderate, 3: important, 4: critical, total } = totalRisks;
56
+
57
+ // eslint-disable-next-line react/prop-types
58
+ const LegendLabel = ({ index, ...rest }) => (
59
+ <a key={index} onClick={() => onChartClick(null, { index })}>
60
+ <ChartLabel {...rest} />
61
+ </a>
62
+ );
63
+
64
+ const legend = (
65
+ <ChartLegend
66
+ height={400}
67
+ width={200}
68
+ fontSize={14}
69
+ rowGutter={{ top: -5, bottom: -5 }}
70
+ orientation="vertical"
71
+ labelComponent={<LegendLabel />}
72
+ data={[
73
+ { name: `${low.title}: ${low.value}` },
74
+ { name: `${moderate.title}: ${moderate.value}` },
75
+ { name: `${important.title}: ${important.value}` },
76
+ { name: `${critical.title}: ${critical.value}` },
77
+ ]}
78
+ />
79
+ );
80
+
81
+ const cardBody = (
82
+ <ChartDonut
83
+ ariaDesc="Number of recommendations total-risks"
84
+ constrainToVisibleArea
85
+ data={[
86
+ { x: low.title, y: low.value },
87
+ { x: moderate.title, y: moderate.value },
88
+ { x: important.title, y: important.value },
89
+ { x: critical.title, y: critical.value },
90
+ ]}
91
+ labels={({ datum: { x, y } }) => `${x}: ${y}`}
92
+ legendComponent={legend}
93
+ legendPosition="right"
94
+ subTitle="Recommendations"
95
+ title={`${total}`}
96
+ padding={{
97
+ bottom: 20,
98
+ left: 20,
99
+ right: 140,
100
+ top: 20,
101
+ }}
102
+ width={350}
103
+ theme={theme}
104
+ events={[
105
+ {
106
+ target: 'data',
107
+ eventHandlers: {
108
+ onClick: onChartClick,
109
+ onMouseOver: onChartHover,
110
+ onMouseOut: () => [{ mutation: () => null }],
111
+ },
112
+ },
113
+ ]}
114
+ />
115
+ );
116
+
117
+ return (
118
+ <CardTemplate
119
+ header={__('Total Risks')}
120
+ dropdownItems={[
121
+ <DropdownItem
122
+ key="insights-tab"
123
+ onClick={() => hashHistory.push(`/Insights`)}
124
+ >
125
+ {__('View all recommendations')}
126
+ </DropdownItem>,
127
+ ]}
128
+ >
129
+ <SkeletonLoader
130
+ status={status}
131
+ emptyState={
132
+ <Bullseye>
133
+ <Title headingLevel="h4"> {__('No results found')} </Title>
134
+ </Bullseye>
135
+ }
136
+ >
137
+ <div id="rh-cloud-total-risk-card">{cardBody}</div>
138
+ </SkeletonLoader>
139
+ </CardTemplate>
140
+ );
141
+ };
142
+
143
+ InsightsTotalRiskCard.propTypes = {
144
+ hostDetails: PropTypes.object.isRequired,
145
+ };
146
+
147
+ export default InsightsTotalRiskCard;
@@ -0,0 +1,103 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useDispatch, useSelector } from 'react-redux';
4
+ import SearchBar from 'foremanReact/components/SearchBar';
5
+ import { translate as __ } from 'foremanReact/common/I18n';
6
+ import {
7
+ Grid,
8
+ GridItem,
9
+ Dropdown,
10
+ DropdownItem,
11
+ KebabToggle,
12
+ } from '@patternfly/react-core';
13
+ import { ExternalLinkAltIcon } from '@patternfly/react-icons';
14
+ import InsightsTable from '../InsightsCloudSync/Components/InsightsTable';
15
+ import RemediationModal from '../InsightsCloudSync/Components/RemediationModal';
16
+ import Pagination from '../InsightsCloudSync/Components/InsightsTable/Pagination';
17
+ import { INSIGHTS_SEARCH_PROPS } from '../InsightsCloudSync/InsightsCloudSyncConstants';
18
+ import { fetchInsights } from '../InsightsCloudSync/Components/InsightsTable/InsightsTableActions';
19
+ import {
20
+ selectSearch,
21
+ selectHits,
22
+ } from '../InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors';
23
+ import { redHatAdvisorSystems } from '../InsightsCloudSync/InsightsCloudSyncHelpers';
24
+
25
+ const NewHostDetailsTab = ({ hostName, router }) => {
26
+ const dispatch = useDispatch();
27
+ const query = useSelector(selectSearch);
28
+ const hits = useSelector(selectHits);
29
+
30
+ useEffect(() => () => router.replace({ search: null }), [router]);
31
+
32
+ const onSearch = q => dispatch(fetchInsights({ query: q, page: 1 }));
33
+
34
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
35
+ const onSatInsightsClick = () =>
36
+ router.push({ pathname: '/foreman_rh_cloud/insights_cloud' });
37
+
38
+ const dropdownItems = [
39
+ <DropdownItem key="insights-link">
40
+ <a onClick={onSatInsightsClick}>{__('Go to Satellite Insights page')}</a>
41
+ </DropdownItem>,
42
+ ];
43
+
44
+ if (hits.length) {
45
+ const { host_uuid: uuid } = hits[0];
46
+ dropdownItems.push(
47
+ <DropdownItem key="insights-advisor-link">
48
+ <a
49
+ href={redHatAdvisorSystems(uuid)}
50
+ target="_blank"
51
+ rel="noopener noreferrer"
52
+ >
53
+ {__('View in Red Hat Insights')}
54
+ {' '}
55
+ <ExternalLinkAltIcon />
56
+ </a>
57
+ </DropdownItem>
58
+ );
59
+ }
60
+
61
+ return (
62
+ <Grid id="new_host_details_insights_tab" hasGutter>
63
+ <GridItem span={5}>
64
+ <SearchBar
65
+ data={INSIGHTS_SEARCH_PROPS}
66
+ onSearch={onSearch}
67
+ initialQuery={query}
68
+ />
69
+ </GridItem>
70
+ <GridItem span={4}>
71
+ <RemediationModal />
72
+ <Dropdown
73
+ className="insights-dropdown"
74
+ onSelect={() => setIsDropdownOpen(false)}
75
+ toggle={
76
+ <KebabToggle onToggle={isOpen => setIsDropdownOpen(isOpen)} />
77
+ }
78
+ isOpen={isDropdownOpen}
79
+ isPlain
80
+ dropdownItems={dropdownItems}
81
+ />
82
+ </GridItem>
83
+ <GridItem span={3}>
84
+ <Pagination variant="top" isCompact />
85
+ </GridItem>
86
+ <GridItem>
87
+ <InsightsTable hideHost hostname={hostName} />
88
+ </GridItem>
89
+ </Grid>
90
+ );
91
+ };
92
+
93
+ NewHostDetailsTab.propTypes = {
94
+ hostName: PropTypes.string,
95
+ router: PropTypes.object,
96
+ };
97
+
98
+ NewHostDetailsTab.defaultProps = {
99
+ hostName: '',
100
+ router: {},
101
+ };
102
+
103
+ export default NewHostDetailsTab;
@@ -1 +1,2 @@
1
1
  export const useForemanSettings = () => ({ perPage: 20 });
2
+ export const useForemanOrganization = () => ({ title: 'some-org' });
@@ -0,0 +1,11 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import { Helmet } from 'react-helmet';
4
+
5
+ const Head = ({ children }) => <Helmet>{children}</Helmet>;
6
+
7
+ Head.propTypes = {
8
+ children: PropTypes.node.isRequired,
9
+ };
10
+
11
+ export default Head;
@@ -0,0 +1,24 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Dropdown, KebabToggle } from '@patternfly/react-core';
4
+
5
+ const DropdownToggle = ({ items, ...props }) => {
6
+ const [isOpen, setOpen] = useState(false);
7
+ return (
8
+ <Dropdown
9
+ onSelect={() => setOpen(false)}
10
+ toggle={<KebabToggle onToggle={value => setOpen(value)} />}
11
+ isOpen={isOpen}
12
+ isPlain
13
+ dropdownItems={items}
14
+ position="right"
15
+ {...props}
16
+ />
17
+ );
18
+ };
19
+
20
+ DropdownToggle.propTypes = {
21
+ items: PropTypes.array.isRequired,
22
+ };
23
+
24
+ export default DropdownToggle;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { get } from 'foremanReact/redux/API';
3
3
  import { withInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
4
- import { addToast } from 'foremanReact/redux/actions/toasts';
4
+ import { addToast } from 'foremanReact/components/ToastsList';
5
5
  import { translate as __ } from 'foremanReact/common/I18n';
6
6
  import { foremanTaskDetailsUrl } from './ForemanTasksHelpers';
7
7
  import { foremanUrl } from '../../ForemanRhCloudHelpers';
@@ -7,6 +7,7 @@ exports[`InsightsCloudSync helpers should return insights cloud Url 1`] = `
7
7
  id="rh-cloud-switcher-some-id"
8
8
  isChecked={true}
9
9
  isDisabled={false}
10
+ isReversed={false}
10
11
  label={
11
12
  <div>
12
13
  some-label
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_rh_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.31
4
+ version: 5.0.31
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Red Hat Cloud team
@@ -158,6 +158,8 @@ files:
158
158
  - app/models/insights_rule.rb
159
159
  - app/models/inventory_sync/inventory_status.rb
160
160
  - app/models/setting/rh_cloud.rb
161
+ - app/models/task_output_line.rb
162
+ - app/models/task_output_status.rb
161
163
  - app/overrides/hosts_list.rb
162
164
  - app/overrides/layouts/base/styles.html.erb.deface
163
165
  - app/services/foreman_rh_cloud/branch_info.rb
@@ -189,6 +191,7 @@ files:
189
191
  - db/migrate/20210307000001_add_unique_to_insights_facet.foreman_rh_cloud.rb
190
192
  - db/migrate/20210404000001_change_resolutions.foreman_rh_cloud.rb
191
193
  - db/migrate/20210720000001_remove_old_insights_statuses.foreman_rh_cloud.rb
194
+ - db/migrate/20211027000001_create_task_output.foreman_rh_cloud.rb
192
195
  - db/seeds.d/179_ui_notifications.rb
193
196
  - db/seeds.d/50_job_templates.rb
194
197
  - lib/foreman_inventory_upload.rb
@@ -260,6 +263,7 @@ files:
260
263
  - test/unit/insights_facet_test.rb
261
264
  - test/unit/metadata_generator_test.rb
262
265
  - test/unit/rh_cloud_http_proxy_test.rb
266
+ - test/unit/rh_cloud_permissions_test.rb
263
267
  - test/unit/services/foreman_rh_cloud/branch_info_test.rb
264
268
  - test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb
265
269
  - test/unit/services/foreman_rh_cloud/cloud_status_service_test.rb
@@ -593,6 +597,8 @@ files:
593
597
  - webpack/InsightsHostDetailsTab/InsightsTabConstants.js
594
598
  - webpack/InsightsHostDetailsTab/InsightsTabReducer.js
595
599
  - webpack/InsightsHostDetailsTab/InsightsTabSelectors.js
600
+ - webpack/InsightsHostDetailsTab/InsightsTotalRiskChart.js
601
+ - webpack/InsightsHostDetailsTab/NewHostDetailsTab.js
596
602
  - webpack/InsightsHostDetailsTab/__tests__/InsightsTab.fixtures.js
597
603
  - webpack/InsightsHostDetailsTab/__tests__/InsightsTab.test.js
598
604
  - webpack/InsightsHostDetailsTab/__tests__/InsightsTabActions.test.js
@@ -610,12 +616,12 @@ files:
610
616
  - webpack/__mocks__/foremanReact/common/I18n.js
611
617
  - webpack/__mocks__/foremanReact/common/MountingService.js
612
618
  - webpack/__mocks__/foremanReact/common/helpers.js
619
+ - webpack/__mocks__/foremanReact/components/Head.js
613
620
  - webpack/__mocks__/foremanReact/components/Layout/LayoutConstants.js
614
- - webpack/__mocks__/foremanReact/components/Layout/LayoutSelectors.js
621
+ - webpack/__mocks__/foremanReact/components/ToastsList/index.js
615
622
  - webpack/__mocks__/foremanReact/constants.js
616
623
  - webpack/__mocks__/foremanReact/redux/API/APISelectors.js
617
624
  - webpack/__mocks__/foremanReact/redux/API/index.js
618
- - webpack/__mocks__/foremanReact/redux/actions/toasts.js
619
625
  - webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware.js
620
626
  - webpack/__mocks__/foremanReact/routes/RouterSelector.js
621
627
  - webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js
@@ -625,6 +631,7 @@ files:
625
631
  - webpack/__tests__/__snapshots__/ForemanRhCloudHelpers.test.js.snap
626
632
  - webpack/__tests__/__snapshots__/ForemanRhCloudSelectors.test.js.snap
627
633
  - webpack/__tests__/__snapshots__/ForemanRhCloudTestHelpers.test.js.snap
634
+ - webpack/common/DropdownToggle.js
628
635
  - webpack/common/ForemanTasks/ForemanTasksActions.js
629
636
  - webpack/common/ForemanTasks/ForemanTasksHelpers.js
630
637
  - webpack/common/ForemanTasks/index.js
@@ -691,6 +698,7 @@ test_files:
691
698
  - test/unit/insights_facet_test.rb
692
699
  - test/unit/metadata_generator_test.rb
693
700
  - test/unit/rh_cloud_http_proxy_test.rb
701
+ - test/unit/rh_cloud_permissions_test.rb
694
702
  - test/unit/services/foreman_rh_cloud/branch_info_test.rb
695
703
  - test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb
696
704
  - test/unit/services/foreman_rh_cloud/cloud_status_service_test.rb
@@ -1 +0,0 @@
1
- export const selectCurrentOrganization = state => 'some-org';