diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-20 18:40:28 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-20 18:40:28 +0300 |
commit | b595cb0c1dec83de5bdee18284abe86614bed33b (patch) | |
tree | 8c3d4540f193c5ff98019352f554e921b3a41a72 /app/assets/javascripts/google_cloud | |
parent | 2f9104a328fc8a4bddeaa4627b595166d24671d0 (diff) |
Add latest changes from gitlab-org/gitlab@15-2-stable-eev15.2.0-rc42
Diffstat (limited to 'app/assets/javascripts/google_cloud')
23 files changed, 757 insertions, 226 deletions
diff --git a/app/assets/javascripts/google_cloud/components/app.vue b/app/assets/javascripts/google_cloud/components/app.vue deleted file mode 100644 index b3d773e6bee..00000000000 --- a/app/assets/javascripts/google_cloud/components/app.vue +++ /dev/null @@ -1,63 +0,0 @@ -<script> -import { __ } from '~/locale'; - -import Home from './home.vue'; -import IncubationBanner from './incubation_banner.vue'; -import ServiceAccountsForm from './service_accounts_form.vue'; -import GcpRegionsForm from './gcp_regions_form.vue'; -import NoGcpProjects from './errors/no_gcp_projects.vue'; -import GcpError from './errors/gcp_error.vue'; - -const SCREEN_GCP_ERROR = 'gcp_error'; -const SCREEN_HOME = 'home'; -const SCREEN_NO_GCP_PROJECTS = 'no_gcp_projects'; -const SCREEN_SERVICE_ACCOUNTS_FORM = 'service_accounts_form'; -const SCREEN_GCP_REGIONS_FORM = 'gcp_regions_form'; - -export default { - components: { - IncubationBanner, - }, - inheritAttrs: false, - props: { - screen: { - required: true, - type: String, - }, - }, - computed: { - mainComponent() { - switch (this.screen) { - case SCREEN_HOME: - return Home; - case SCREEN_GCP_ERROR: - return GcpError; - case SCREEN_NO_GCP_PROJECTS: - return NoGcpProjects; - case SCREEN_SERVICE_ACCOUNTS_FORM: - return ServiceAccountsForm; - case SCREEN_GCP_REGIONS_FORM: - return GcpRegionsForm; - default: - throw new Error(__('Unknown screen')); - } - }, - }, - methods: { - feedbackUrl(template) { - return `https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/feedback/-/issues/new?issuable_template=${template}`; - }, - }, -}; -</script> - -<template> - <div> - <incubation-banner - :share-feedback-url="feedbackUrl('general_feedback')" - :report-bug-url="feedbackUrl('report_bug')" - :feature-request-url="feedbackUrl('feature_request')" - /> - <component :is="mainComponent" v-bind="$attrs" /> - </div> -</template> diff --git a/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue b/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue deleted file mode 100644 index 90aa0e1ae68..00000000000 --- a/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue +++ /dev/null @@ -1,29 +0,0 @@ -<script> -import { GlAlert } from '@gitlab/ui'; -import { __ } from '~/locale'; - -export default { - components: { GlAlert }, - props: { - error: { - type: String, - required: true, - }, - }, - i18n: { - title: __('Google Cloud project misconfigured'), - description: __( - 'GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:', - ), - }, -}; -</script> - -<template> - <gl-alert :dismissible="false" variant="warning" :title="$options.i18n.title"> - {{ $options.i18n.description }} - <blockquote> - <code>{{ error }}</code> - </blockquote> - </gl-alert> -</template> diff --git a/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue b/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue deleted file mode 100644 index da229ac3f0e..00000000000 --- a/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue +++ /dev/null @@ -1,26 +0,0 @@ -<script> -import { GlAlert, GlButton } from '@gitlab/ui'; -import { __ } from '~/locale'; - -export default { - components: { GlAlert, GlButton }, - i18n: { - title: __('Google Cloud project required'), - description: __( - 'You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page.', - ), - createLabel: __('Create Google Cloud project'), - }, -}; -</script> - -<template> - <gl-alert :dismissible="false" variant="warning" :title="$options.i18n.title"> - {{ $options.i18n.description }} - <template #actions> - <gl-button href="https://console.cloud.google.com/projectcreate" target="_blank"> - {{ $options.i18n.createLabel }} - </gl-button> - </template> - </gl-alert> -</template> diff --git a/app/assets/javascripts/google_cloud/components/google_cloud_menu.vue b/app/assets/javascripts/google_cloud/components/google_cloud_menu.vue new file mode 100644 index 00000000000..d6b7c702b54 --- /dev/null +++ b/app/assets/javascripts/google_cloud/components/google_cloud_menu.vue @@ -0,0 +1,85 @@ +<script> +import { s__ } from '~/locale'; + +const CONFIGURATION_KEY = 'configuration'; +const DEPLOYMENTS_KEY = 'deployments'; +const DATABASES_KEY = 'databases'; + +const i18n = { + configuration: { title: s__('CloudSeed|Configuration') }, + deployments: { title: s__('CloudSeed|Deployments') }, + databases: { title: s__('CloudSeed|Databases') }, +}; + +export default { + props: { + active: { + type: String, + required: true, + }, + configurationUrl: { + type: String, + required: true, + }, + deploymentsUrl: { + type: String, + required: true, + }, + databasesUrl: { + type: String, + required: true, + }, + }, + computed: { + isConfigurationActive() { + return this.active === CONFIGURATION_KEY; + }, + isDeploymentsActive() { + return this.active === DEPLOYMENTS_KEY; + }, + isDatabasesActive() { + return this.active === DATABASES_KEY; + }, + }, + i18n, +}; +</script> +<template> + <div class="tabs gl-tabs"> + <ul role="tablist" class="nav gl-tabs-nav"> + <li role="presentation" class="nav-item"> + <a + data-testid="configurationLink" + role="tab" + :href="configurationUrl" + class="nav-link gl-tab-nav-item" + :class="{ 'gl-tab-nav-item-active': isConfigurationActive }" + > + {{ $options.i18n.configuration.title }}</a + > + </li> + <li role="presentation" class="nav-item"> + <a + data-testid="deploymentsLink" + role="tab" + :href="deploymentsUrl" + class="nav-link gl-tab-nav-item" + :class="{ 'gl-tab-nav-item-active': isDeploymentsActive }" + > + {{ $options.i18n.deployments.title }} + </a> + </li> + <li role="presentation" class="nav-item"> + <a + data-testid="databasesLink" + role="tab" + :href="databasesUrl" + class="nav-link gl-tab-nav-item" + :class="{ 'gl-tab-nav-item-active': isDatabasesActive }" + > + {{ $options.i18n.databases.title }} + </a> + </li> + </ul> + </div> +</template> diff --git a/app/assets/javascripts/google_cloud/components/home.vue b/app/assets/javascripts/google_cloud/components/home.vue deleted file mode 100644 index e41337e2679..00000000000 --- a/app/assets/javascripts/google_cloud/components/home.vue +++ /dev/null @@ -1,81 +0,0 @@ -<script> -import { GlTabs, GlTab } from '@gitlab/ui'; -import DeploymentsServiceTable from './deployments_service_table.vue'; -import RevokeOauth from './revoke_oauth.vue'; -import ServiceAccountsList from './service_accounts_list.vue'; -import GcpRegionsList from './gcp_regions_list.vue'; - -export default { - components: { - GlTabs, - GlTab, - DeploymentsServiceTable, - RevokeOauth, - ServiceAccountsList, - GcpRegionsList, - }, - props: { - serviceAccounts: { - type: Array, - required: true, - }, - createServiceAccountUrl: { - type: String, - required: true, - }, - configureGcpRegionsUrl: { - type: String, - required: true, - }, - emptyIllustrationUrl: { - type: String, - required: true, - }, - enableCloudRunUrl: { - type: String, - required: true, - }, - enableCloudStorageUrl: { - type: String, - required: true, - }, - gcpRegions: { - type: Array, - required: true, - }, - revokeOauthUrl: { - type: String, - required: true, - }, - }, -}; -</script> - -<template> - <gl-tabs> - <gl-tab :title="__('Configuration')"> - <service-accounts-list - class="gl-mx-4" - :list="serviceAccounts" - :create-url="createServiceAccountUrl" - :empty-illustration-url="emptyIllustrationUrl" - /> - <hr /> - <gcp-regions-list - class="gl-mx-4" - :empty-illustration-url="emptyIllustrationUrl" - :create-url="configureGcpRegionsUrl" - :list="gcpRegions" - /> - <hr v-if="revokeOauthUrl" /> - <revoke-oauth v-if="revokeOauthUrl" :url="revokeOauthUrl" /> - </gl-tab> - <gl-tab :title="__('Deployments')"> - <deployments-service-table - :cloud-run-url="enableCloudRunUrl" - :cloud-storage-url="enableCloudStorageUrl" - /> - </gl-tab> - <gl-tab :title="__('Services')" disabled /> - </gl-tabs> -</template> diff --git a/app/assets/javascripts/google_cloud/components/incubation_banner.vue b/app/assets/javascripts/google_cloud/components/incubation_banner.vue index 652b8c1aecb..128b3dcb1d9 100644 --- a/app/assets/javascripts/google_cloud/components/incubation_banner.vue +++ b/app/assets/javascripts/google_cloud/components/incubation_banner.vue @@ -1,22 +1,20 @@ <script> import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui'; +const FEATURE_REQUEST_KEY = 'feature_request'; +const REPORT_BUG_KEY = 'report_bug'; +const GENERAL_FEEDBACK_KEY = 'general_feedback'; + export default { components: { GlAlert, GlLink, GlSprintf }, - props: { - shareFeedbackUrl: { - required: true, - type: String, - }, - reportBugUrl: { - required: true, - type: String, - }, - featureRequestUrl: { - required: true, - type: String, + methods: { + feedbackUrl(template) { + return `https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/feedback/-/issues/new?issuable_template=${template}`; }, }, + FEATURE_REQUEST_KEY, + REPORT_BUG_KEY, + GENERAL_FEEDBACK_KEY, }; </script> @@ -31,13 +29,13 @@ export default { " > <template #featureLink="{ content }"> - <gl-link :href="featureRequestUrl">{{ content }}</gl-link> + <gl-link :href="feedbackUrl($options.FEATURE_REQUEST_KEY)">{{ content }}</gl-link> </template> <template #bugLink="{ content }"> - <gl-link :href="reportBugUrl">{{ content }}</gl-link> + <gl-link :href="feedbackUrl($options.REPORT_BUG_KEY)">{{ content }}</gl-link> </template> <template #feedbackLink="{ content }"> - <gl-link :href="shareFeedbackUrl">{{ content }}</gl-link> + <gl-link :href="feedbackUrl($options.GENERAL_FEEDBACK_KEY)">{{ content }}</gl-link> </template> </gl-sprintf> </gl-alert> diff --git a/app/assets/javascripts/google_cloud/configuration/index.js b/app/assets/javascripts/google_cloud/configuration/index.js new file mode 100644 index 00000000000..580315588d0 --- /dev/null +++ b/app/assets/javascripts/google_cloud/configuration/index.js @@ -0,0 +1,11 @@ +import Vue from 'vue'; +import Panel from './panel.vue'; + +export default (containerId = '#js-google-cloud-configuration') => { + const element = document.querySelector(containerId); + const { ...attrs } = JSON.parse(element.getAttribute('data')); + return new Vue({ + el: element, + render: (createElement) => createElement(Panel, { attrs }), + }); +}; diff --git a/app/assets/javascripts/google_cloud/configuration/panel.vue b/app/assets/javascripts/google_cloud/configuration/panel.vue new file mode 100644 index 00000000000..ee046eb1988 --- /dev/null +++ b/app/assets/javascripts/google_cloud/configuration/panel.vue @@ -0,0 +1,88 @@ +<script> +import GcpRegionsList from '../gcp_regions/list.vue'; +import GoogleCloudMenu from '../components/google_cloud_menu.vue'; +import IncubationBanner from '../components/incubation_banner.vue'; +import RevokeOauth from '../components/revoke_oauth.vue'; +import ServiceAccountsList from '../service_accounts/list.vue'; + +export default { + components: { + GcpRegionsList, + GoogleCloudMenu, + IncubationBanner, + RevokeOauth, + ServiceAccountsList, + }, + props: { + configurationUrl: { + type: String, + required: true, + }, + deploymentsUrl: { + type: String, + required: true, + }, + databasesUrl: { + type: String, + required: true, + }, + serviceAccounts: { + type: Array, + required: true, + }, + createServiceAccountUrl: { + type: String, + required: true, + }, + emptyIllustrationUrl: { + type: String, + required: true, + }, + configureGcpRegionsUrl: { + type: String, + required: true, + }, + gcpRegions: { + type: Array, + required: true, + }, + revokeOauthUrl: { + type: String, + required: true, + }, + }, +}; +</script> + +<template> + <div> + <incubation-banner /> + + <google-cloud-menu + active="configuration" + :configuration-url="configurationUrl" + :deployments-url="deploymentsUrl" + :databases-url="databasesUrl" + /> + + <service-accounts-list + class="gl-mx-4" + :list="serviceAccounts" + :create-url="createServiceAccountUrl" + :empty-illustration-url="emptyIllustrationUrl" + /> + + <hr /> + + <gcp-regions-list + class="gl-mx-4" + :empty-illustration-url="emptyIllustrationUrl" + :create-url="configureGcpRegionsUrl" + :list="gcpRegions" + /> + + <hr v-if="revokeOauthUrl" /> + + <revoke-oauth v-if="revokeOauthUrl" :url="revokeOauthUrl" /> + </div> +</template> diff --git a/app/assets/javascripts/google_cloud/databases/cloudsql/create_instance_form.vue b/app/assets/javascripts/google_cloud/databases/cloudsql/create_instance_form.vue new file mode 100644 index 00000000000..0ac561b6132 --- /dev/null +++ b/app/assets/javascripts/google_cloud/databases/cloudsql/create_instance_form.vue @@ -0,0 +1,132 @@ +<script> +import { GlButton, GlFormCheckbox, GlFormGroup, GlFormSelect } from '@gitlab/ui'; +import { s__ } from '~/locale'; + +const i18n = { + gcpProjectLabel: s__('CloudSeed|Google Cloud project'), + gcpProjectDescription: s__( + 'CloudSeed|Database instance is generated within the selected Google Cloud project', + ), + refsLabel: s__('CloudSeed|Refs'), + refsDescription: s__( + 'CloudSeed|Generated database instance is linked to the selected branch or tag', + ), + databaseVersionLabel: s__('CloudSeed|Database version'), + tierLabel: s__('CloudSeed|Machine type'), + tierDescription: s__('CloudSeed|Determines memory and virtual cores available to your instance'), + checkboxLabel: s__( + 'CloudSeed|I accept Google Cloud pricing and responsibilities involved with managing database instances', + ), + cancelLabel: s__('CloudSeed|Cancel'), + submitLabel: s__('CloudSeed|Create instance'), + all: s__('CloudSeed|All'), +}; + +export default { + ALL_REFS: '*', + components: { + GlButton, + GlFormCheckbox, + GlFormGroup, + GlFormSelect, + }, + props: { + cancelPath: { required: true, type: String }, + gcpProjects: { required: true, type: Array }, + refs: { required: true, type: Array }, + formTitle: { required: true, type: String }, + formDescription: { required: true, type: String }, + databaseVersions: { required: true, type: Array }, + tiers: { required: true, type: Array }, + }, + i18n, +}; +</script> +<template> + <div> + <header class="gl-my-5 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid"> + <h2 class="gl-font-size-h1">{{ formTitle }}</h2> + <p>{{ formDescription }}</p> + </header> + + <gl-form-group + data-testid="form_group_gcp_project" + label-for="gcp_project" + :label="$options.i18n.gcpProjectLabel" + :description="$options.i18n.gcpProjectDescription" + > + <gl-form-select id="gcp_project" data-testid="select_gcp_project" name="gcp_project" required> + <option + v-for="gcpProject in gcpProjects" + :key="gcpProject.project_id" + :value="gcpProject.project_id" + > + {{ gcpProject.name }} + </option> + </gl-form-select> + </gl-form-group> + + <gl-form-group + data-testid="form_group_environments" + label-for="ref" + :label="$options.i18n.refsLabel" + :description="$options.i18n.refsDescription" + > + <gl-form-select id="ref" data-testid="select_environments" name="ref" required> + <option :value="$options.ALL_REFS">{{ $options.i18n.all }}</option> + <option v-for="ref in refs" :key="ref" :value="ref"> + {{ ref }} + </option> + </gl-form-select> + </gl-form-group> + + <gl-form-group + data-testid="form_group_tier" + label-for="tier" + :label="$options.i18n.tierLabel" + :description="$options.i18n.tierDescription" + > + <gl-form-select id="tier" data-testid="select_tier" name="tier" required> + <option v-for="tier in tiers" :key="tier.value" :value="tier.value"> + {{ tier.label }} + </option> + </gl-form-select> + </gl-form-group> + + <gl-form-group + data-testid="form_group_database_version" + label-for="database-version" + :label="$options.i18n.databaseVersionLabel" + > + <gl-form-select + id="database-version" + data-testid="select_database_version" + name="database_version" + required + > + <option + v-for="databaseVersion in databaseVersions" + :key="databaseVersion.value" + :value="databaseVersion.value" + > + {{ databaseVersion.label }} + </option> + </gl-form-select> + </gl-form-group> + + <gl-form-group> + <gl-form-checkbox name="confirmation" required> + {{ $options.i18n.checkboxLabel }} + </gl-form-checkbox> + </gl-form-group> + + <div class="form-actions row"> + <gl-button type="submit" category="primary" variant="confirm" data-testid="submit-button"> + {{ $options.i18n.submitLabel }} + </gl-button> + <gl-button class="gl-ml-1" :href="cancelPath" data-testid="cancel-button">{{ + $options.i18n.cancelLabel + }}</gl-button> + </div> + </div> +</template> diff --git a/app/assets/javascripts/google_cloud/databases/cloudsql/instance_table.vue b/app/assets/javascripts/google_cloud/databases/cloudsql/instance_table.vue new file mode 100644 index 00000000000..823895214df --- /dev/null +++ b/app/assets/javascripts/google_cloud/databases/cloudsql/instance_table.vue @@ -0,0 +1,75 @@ +<script> +import { GlEmptyState, GlLink, GlTable } from '@gitlab/ui'; +import { encodeSaferUrl, setUrlParams } from '~/lib/utils/url_utility'; +import { s__ } from '~/locale'; + +const i18n = { + noInstancesTitle: s__('CloudSeed|No instances'), + noInstancesDescription: s__('CloudSeed|There are no instances to display.'), + title: s__('CloudSeed|Instances'), + description: s__('CloudSeed|Database instances associated with this project'), +}; + +export default { + components: { GlEmptyState, GlLink, GlTable }, + props: { + cloudsqlInstances: { + type: Array, + required: true, + }, + emptyIllustrationUrl: { + type: String, + required: true, + }, + }, + computed: { + tableData() { + return this.cloudsqlInstances.filter((instance) => instance.instance_name); + }, + }, + methods: { + gcpProjectUrl(id) { + return setUrlParams({ project: id }, 'https://console.cloud.google.com/sql/instances'); + }, + instanceUrl(name, id) { + const saferName = encodeSaferUrl(name); + + return setUrlParams( + { project: id }, + `https://console.cloud.google.com/sql/instances/${saferName}/overview`, + ); + }, + }, + fields: [ + { key: 'ref', label: s__('CloudSeed|Environment') }, + { key: 'gcp_project', label: s__('CloudSeed|Google Cloud Project') }, + { key: 'instance_name', label: s__('CloudSeed|CloudSQL Instance') }, + { key: 'version', label: s__('CloudSeed|Version') }, + ], + i18n, +}; +</script> + +<template> + <div class="gl-mx-3"> + <gl-empty-state + v-if="tableData.length === 0" + :title="$options.i18n.noInstancesTitle" + :description="$options.i18n.noInstancesDescription" + :svg-path="emptyIllustrationUrl" + /> + + <div v-else> + <h2 class="gl-font-size-h2">{{ $options.i18n.title }}</h2> + <p>{{ $options.i18n.description }}</p> + <gl-table :fields="$options.fields" :items="tableData"> + <template #cell(gcp_project)="{ value }"> + <gl-link :href="gcpProjectUrl(value)">{{ value }}</gl-link> + </template> + <template #cell(instance_name)="{ item: { instance_name, gcp_project } }"> + <a :href="instanceUrl(instance_name, gcp_project)">{{ instance_name }}</a> + </template> + </gl-table> + </div> + </div> +</template> diff --git a/app/assets/javascripts/google_cloud/databases/index.js b/app/assets/javascripts/google_cloud/databases/index.js new file mode 100644 index 00000000000..e240a1116e8 --- /dev/null +++ b/app/assets/javascripts/google_cloud/databases/index.js @@ -0,0 +1,11 @@ +import Vue from 'vue'; +import Panel from './panel.vue'; + +export default (containerId = '#js-google-cloud-databases') => { + const element = document.querySelector(containerId); + const { ...attrs } = JSON.parse(element.getAttribute('data')); + return new Vue({ + el: element, + render: (createElement) => createElement(Panel, { attrs }), + }); +}; diff --git a/app/assets/javascripts/google_cloud/databases/panel.vue b/app/assets/javascripts/google_cloud/databases/panel.vue new file mode 100644 index 00000000000..e2f18c286a5 --- /dev/null +++ b/app/assets/javascripts/google_cloud/databases/panel.vue @@ -0,0 +1,38 @@ +<script> +import GoogleCloudMenu from '../components/google_cloud_menu.vue'; +import IncubationBanner from '../components/incubation_banner.vue'; + +export default { + components: { + IncubationBanner, + GoogleCloudMenu, + }, + props: { + configurationUrl: { + type: String, + required: true, + }, + deploymentsUrl: { + type: String, + required: true, + }, + databasesUrl: { + type: String, + required: true, + }, + }, +}; +</script> + +<template> + <div> + <incubation-banner /> + + <google-cloud-menu + active="databases" + :configuration-url="configurationUrl" + :deployments-url="deploymentsUrl" + :databases-url="databasesUrl" + /> + </div> +</template> diff --git a/app/assets/javascripts/google_cloud/databases/service_table.vue b/app/assets/javascripts/google_cloud/databases/service_table.vue new file mode 100644 index 00000000000..80bd6ef28fb --- /dev/null +++ b/app/assets/javascripts/google_cloud/databases/service_table.vue @@ -0,0 +1,221 @@ +<script> +import { GlAlert, GlButton, GlLink, GlSprintf, GlTable } from '@gitlab/ui'; +import { helpPagePath } from '~/helpers/help_page_helper'; +import { s__ } from '~/locale'; + +const KEY_CLOUDSQL_POSTGRES = 'cloudsql-postgres'; +const KEY_CLOUDSQL_MYSQL = 'cloudsql-mysql'; +const KEY_CLOUDSQL_SQLSERVER = 'cloudsql-sqlserver'; +const KEY_ALLOYDB_POSTGRES = 'alloydb-postgres'; +const KEY_MEMORYSTORE_REDIS = 'memorystore-redis'; +const KEY_FIRESTORE = 'firestore'; + +const i18n = { + columnService: s__('CloudSeed|Service'), + columnDescription: s__('CloudSeed|Description'), + cloudsqlPostgresTitle: s__('CloudSeed|Cloud SQL for Postgres'), + cloudsqlPostgresDescription: s__( + 'CloudSeed|Fully managed relational database service for PostgreSQL', + ), + cloudsqlMysqlTitle: s__('CloudSeed|Cloud SQL for MySQL'), + cloudsqlMysqlDescription: s__('CloudSeed|Fully managed relational database service for MySQL'), + cloudsqlSqlserverTitle: s__('CloudSeed|Cloud SQL for SQL Server'), + cloudsqlSqlserverDescription: s__( + 'CloudSeed|Fully managed relational database service for SQL Server', + ), + alloydbPostgresTitle: s__('CloudSeed|AlloyDB for Postgres'), + alloydbPostgresDescription: s__( + 'CloudSeed|Fully managed PostgreSQL-compatible service for high-demand workloads', + ), + memorystoreRedisTitle: s__('CloudSeed|Memorystore for Redis'), + memorystoreRedisDescription: s__( + 'CloudSeed|Scalable, secure, and highly available in-memory service for Redis', + ), + firestoreTitle: s__('CloudSeed|Cloud Firestore'), + firestoreDescription: s__( + 'CloudSeed|Flexible, scalable NoSQL cloud database for client- and server-side development', + ), + createInstance: s__('CloudSeed|Create instance'), + createCluster: s__('CloudSeed|Create cluster'), + createDatabase: s__('CloudSeed|Create database'), + title: s__('CloudSeed|Services'), + description: s__('CloudSeed|Available database services through which instances may be created'), + pricingAlert: s__( + 'CloudSeed|Learn more about pricing for %{cloudsqlPricingStart}Cloud SQL%{cloudsqlPricingEnd}, %{alloydbPricingStart}Alloy DB%{alloydbPricingEnd}, %{memorystorePricingStart}Memorystore%{memorystorePricingEnd} and %{firestorePricingStart}Firestore%{firestorePricingEnd}.', + ), + secretManagersDescription: s__( + 'CloudSeed|Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}', + ), +}; + +const helpUrlSecrets = helpPagePath('ee/ci/secrets'); + +export default { + components: { GlAlert, GlButton, GlLink, GlSprintf, GlTable }, + props: { + cloudsqlPostgresUrl: { + type: String, + required: true, + }, + cloudsqlMysqlUrl: { + type: String, + required: true, + }, + cloudsqlSqlserverUrl: { + type: String, + required: true, + }, + alloydbPostgresUrl: { + type: String, + required: true, + }, + memorystoreRedisUrl: { + type: String, + required: true, + }, + firestoreUrl: { + type: String, + required: true, + }, + }, + methods: { + actionUrl(key) { + switch (key) { + case KEY_CLOUDSQL_POSTGRES: + return this.cloudsqlPostgresUrl; + case KEY_CLOUDSQL_MYSQL: + return this.cloudsqlMysqlUrl; + case KEY_CLOUDSQL_SQLSERVER: + return this.cloudsqlSqlserverUrl; + case KEY_ALLOYDB_POSTGRES: + return this.alloydbPostgresUrl; + case KEY_MEMORYSTORE_REDIS: + return this.memorystoreRedisUrl; + case KEY_FIRESTORE: + return this.firestoreUrl; + default: + return '#'; + } + }, + }, + fields: [ + { key: 'title', label: i18n.columnService }, + { key: 'description', label: i18n.columnDescription }, + { key: 'action', label: '' }, + ], + items: [ + { + title: i18n.cloudsqlPostgresTitle, + description: i18n.cloudsqlPostgresDescription, + action: { + key: KEY_CLOUDSQL_POSTGRES, + title: i18n.createInstance, + testId: 'button-cloudsql-postgres', + }, + }, + { + title: i18n.cloudsqlMysqlTitle, + description: i18n.cloudsqlMysqlDescription, + action: { + disabled: false, + key: KEY_CLOUDSQL_MYSQL, + title: i18n.createInstance, + testId: 'button-cloudsql-mysql', + }, + }, + { + title: i18n.cloudsqlSqlserverTitle, + description: i18n.cloudsqlSqlserverDescription, + action: { + disabled: false, + key: KEY_CLOUDSQL_SQLSERVER, + title: i18n.createInstance, + testId: 'button-cloudsql-sqlserver', + }, + }, + { + title: i18n.alloydbPostgresTitle, + description: i18n.alloydbPostgresDescription, + action: { + disabled: true, + key: KEY_ALLOYDB_POSTGRES, + title: i18n.createCluster, + testId: 'button-alloydb-postgres', + }, + }, + { + title: i18n.memorystoreRedisTitle, + description: i18n.memorystoreRedisDescription, + action: { + disabled: true, + key: KEY_MEMORYSTORE_REDIS, + title: i18n.createInstance, + testId: 'button-memorystore-redis', + }, + }, + { + title: i18n.firestoreTitle, + description: i18n.firestoreDescription, + action: { + disabled: true, + key: KEY_FIRESTORE, + title: i18n.createDatabase, + testId: 'button-firestore', + }, + }, + ], + helpUrlSecrets, + i18n, +}; +</script> + +<template> + <div class="gl-mx-3"> + <h2 class="gl-font-size-h2">{{ $options.i18n.title }}</h2> + <p>{{ $options.i18n.description }}</p> + + <gl-table :fields="$options.fields" :items="$options.items"> + <template #cell(action)="{ value }"> + <gl-button + block + :disabled="value.disabled" + :href="actionUrl(value.key)" + :data-testid="value.testId" + category="secondary" + variant="confirm" + > + {{ value.title }} + </gl-button> + </template> + </gl-table> + + <gl-alert class="gl-mt-5" :dismissible="false" variant="tip"> + <gl-sprintf :message="$options.i18n.pricingAlert"> + <template #cloudsqlPricing="{ content }"> + <gl-link href="https://cloud.google.com/sql/pricing">{{ content }}</gl-link> + </template> + <template #alloydbPricing="{ content }"> + <gl-link href="https://cloud.google.com/alloydb/pricing">{{ content }}</gl-link> + </template> + <template #memorystorePricing="{ content }"> + <gl-link href="https://cloud.google.com/memorystore/docs/redis/pricing">{{ + content + }}</gl-link> + </template> + <template #firestorePricing="{ content }"> + <gl-link href="https://cloud.google.com/firestore/pricing">{{ content }}</gl-link> + </template> + </gl-sprintf> + </gl-alert> + + <gl-alert class="gl-mt-5" :dismissible="false" variant="tip"> + <gl-sprintf :message="$options.i18n.secretManagersDescription"> + <template #docLink="{ content }"> + <gl-link :href="$options.helpUrlSecrets"> + {{ content }} + </gl-link> + </template> + </gl-sprintf> + </gl-alert> + </div> +</template> diff --git a/app/assets/javascripts/google_cloud/deployments/index.js b/app/assets/javascripts/google_cloud/deployments/index.js new file mode 100644 index 00000000000..fcbb2209c40 --- /dev/null +++ b/app/assets/javascripts/google_cloud/deployments/index.js @@ -0,0 +1,11 @@ +import Vue from 'vue'; +import Panel from './panel.vue'; + +export default (containerId = '#js-google-cloud-deployments') => { + const element = document.querySelector(containerId); + const { ...attrs } = JSON.parse(element.getAttribute('data')); + return new Vue({ + el: element, + render: (createElement) => createElement(Panel, { attrs }), + }); +}; diff --git a/app/assets/javascripts/google_cloud/deployments/panel.vue b/app/assets/javascripts/google_cloud/deployments/panel.vue new file mode 100644 index 00000000000..89db132ad5e --- /dev/null +++ b/app/assets/javascripts/google_cloud/deployments/panel.vue @@ -0,0 +1,50 @@ +<script> +import GoogleCloudMenu from '../components/google_cloud_menu.vue'; +import IncubationBanner from '../components/incubation_banner.vue'; +import ServiceTable from './service_table.vue'; + +export default { + components: { + ServiceTable, + IncubationBanner, + GoogleCloudMenu, + }, + props: { + configurationUrl: { + type: String, + required: true, + }, + deploymentsUrl: { + type: String, + required: true, + }, + databasesUrl: { + type: String, + required: true, + }, + enableCloudRunUrl: { + type: String, + required: true, + }, + enableCloudStorageUrl: { + type: String, + required: true, + }, + }, +}; +</script> + +<template> + <div> + <incubation-banner /> + + <google-cloud-menu + active="deployments" + :configuration-url="configurationUrl" + :deployments-url="deploymentsUrl" + :databases-url="databasesUrl" + /> + + <service-table :cloud-run-url="enableCloudRunUrl" :cloud-storage-url="enableCloudStorageUrl" /> + </div> +</template> diff --git a/app/assets/javascripts/google_cloud/components/deployments_service_table.vue b/app/assets/javascripts/google_cloud/deployments/service_table.vue index 26c9fd14dc6..26c9fd14dc6 100644 --- a/app/assets/javascripts/google_cloud/components/deployments_service_table.vue +++ b/app/assets/javascripts/google_cloud/deployments/service_table.vue diff --git a/app/assets/javascripts/google_cloud/components/gcp_regions_form.vue b/app/assets/javascripts/google_cloud/gcp_regions/form.vue index 23011e5a5b0..23011e5a5b0 100644 --- a/app/assets/javascripts/google_cloud/components/gcp_regions_form.vue +++ b/app/assets/javascripts/google_cloud/gcp_regions/form.vue diff --git a/app/assets/javascripts/google_cloud/gcp_regions/index.js b/app/assets/javascripts/google_cloud/gcp_regions/index.js new file mode 100644 index 00000000000..da37c612805 --- /dev/null +++ b/app/assets/javascripts/google_cloud/gcp_regions/index.js @@ -0,0 +1,11 @@ +import Vue from 'vue'; +import Form from './form.vue'; + +export default (containerId = '#js-google-cloud-gcp-regions') => { + const element = document.querySelector(containerId); + const { ...attrs } = JSON.parse(element.getAttribute('data')); + return new Vue({ + el: element, + render: (createElement) => createElement(Form, { attrs }), + }); +}; diff --git a/app/assets/javascripts/google_cloud/components/gcp_regions_list.vue b/app/assets/javascripts/google_cloud/gcp_regions/list.vue index 5d403d5cd65..5d403d5cd65 100644 --- a/app/assets/javascripts/google_cloud/components/gcp_regions_list.vue +++ b/app/assets/javascripts/google_cloud/gcp_regions/list.vue diff --git a/app/assets/javascripts/google_cloud/index.js b/app/assets/javascripts/google_cloud/index.js deleted file mode 100644 index ab9e8227812..00000000000 --- a/app/assets/javascripts/google_cloud/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import Vue from 'vue'; -import App from './components/app.vue'; - -export default () => { - const root = '#js-google-cloud'; - const element = document.querySelector(root); - const { screen, ...attrs } = JSON.parse(element.getAttribute('data')); - return new Vue({ - el: element, - render: (createElement) => createElement(App, { props: { screen }, attrs }), - }); -}; diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue b/app/assets/javascripts/google_cloud/service_accounts/form.vue index faec94e735b..faec94e735b 100644 --- a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue +++ b/app/assets/javascripts/google_cloud/service_accounts/form.vue diff --git a/app/assets/javascripts/google_cloud/service_accounts/index.js b/app/assets/javascripts/google_cloud/service_accounts/index.js new file mode 100644 index 00000000000..5207b44deac --- /dev/null +++ b/app/assets/javascripts/google_cloud/service_accounts/index.js @@ -0,0 +1,11 @@ +import Vue from 'vue'; +import Form from './form.vue'; + +export default (containerId = '#js-google-cloud-service-accounts') => { + const element = document.querySelector(containerId); + const { ...attrs } = JSON.parse(element.getAttribute('data')); + return new Vue({ + el: element, + render: (createElement) => createElement(Form, { attrs }), + }); +}; diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_list.vue b/app/assets/javascripts/google_cloud/service_accounts/list.vue index 4b580c594f5..4b580c594f5 100644 --- a/app/assets/javascripts/google_cloud/components/service_accounts_list.vue +++ b/app/assets/javascripts/google_cloud/service_accounts/list.vue |