Commit 8155ccf4 authored by Vitali Tatarintev's avatar Vitali Tatarintev

Move custom mapping params to HttpIntegrationType

Move custom mapping params to HttpIntegrationType so IntegrationType
doesn't expose them
parent 6c105a39
# frozen_string_literal: true
module Resolvers
module AlertManagement
class HttpIntegrationsResolver < BaseResolver
alias_method :project, :synchronized_object
type Types::AlertManagement::HttpIntegrationType.connection_type, null: true
def resolve(**args)
http_integrations
end
private
def http_integrations
return [] unless Ability.allowed?(current_user, :admin_operations, project)
::AlertManagement::HttpIntegrationsFinder.new(project, {}).execute
end
end
end
end
...@@ -20,3 +20,5 @@ module Types ...@@ -20,3 +20,5 @@ module Types
end end
end end
end end
Types::AlertManagement::HttpIntegrationType.prepend_ee_mod
...@@ -56,5 +56,3 @@ module Types ...@@ -56,5 +56,3 @@ module Types
end end
end end
end end
Types::AlertManagement::IntegrationType.include_if_ee('::EE::Types::AlertManagement::IntegrationType')
...@@ -33,14 +33,6 @@ module Types ...@@ -33,14 +33,6 @@ module Types
def active def active
prometheus_service.manual_configuration? prometheus_service.manual_configuration?
end end
def payload_example
{}
end
def payload_attribute_mappings
[]
end
end end
end end
end end
...@@ -273,6 +273,12 @@ module Types ...@@ -273,6 +273,12 @@ module Types
description: 'Integrations which can receive alerts for the project.', description: 'Integrations which can receive alerts for the project.',
resolver: Resolvers::AlertManagement::IntegrationsResolver resolver: Resolvers::AlertManagement::IntegrationsResolver
field :alert_management_http_integrations,
Types::AlertManagement::HttpIntegrationType.connection_type,
null: true,
description: 'HTTP Integrations which can receive alerts for the project.',
resolver: Resolvers::AlertManagement::HttpIntegrationsResolver
field :releases, field :releases,
Types::ReleaseType.connection_type, Types::ReleaseType.connection_type,
null: true, null: true,
......
...@@ -660,6 +660,41 @@ type AlertManagementHttpIntegration implements AlertManagementIntegration { ...@@ -660,6 +660,41 @@ type AlertManagementHttpIntegration implements AlertManagementIntegration {
url: String url: String
} }
"""
The connection type for AlertManagementHttpIntegration.
"""
type AlertManagementHttpIntegrationConnection {
"""
A list of edges.
"""
edges: [AlertManagementHttpIntegrationEdge]
"""
A list of nodes.
"""
nodes: [AlertManagementHttpIntegration]
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
}
"""
An edge in a connection.
"""
type AlertManagementHttpIntegrationEdge {
"""
A cursor for use in pagination.
"""
cursor: String!
"""
The item at the end of the edge.
"""
node: AlertManagementHttpIntegration
}
""" """
Identifier of AlertManagement::HttpIntegration. Identifier of AlertManagement::HttpIntegration.
""" """
...@@ -686,16 +721,6 @@ interface AlertManagementIntegration { ...@@ -686,16 +721,6 @@ interface AlertManagementIntegration {
""" """
name: String name: String
"""
The custom mapping of GitLab alert attributes to fields from the payload_example.
"""
payloadAttributeMappings: [AlertManagementPayloadAlertMappingField!]
"""
The example of an alert payload.
"""
payloadExample: JsonString
""" """
Token used to authenticate alert notification requests. Token used to authenticate alert notification requests.
""" """
...@@ -931,16 +956,6 @@ type AlertManagementPrometheusIntegration implements AlertManagementIntegration ...@@ -931,16 +956,6 @@ type AlertManagementPrometheusIntegration implements AlertManagementIntegration
""" """
name: String name: String
"""
The custom mapping of GitLab alert attributes to fields from the payload_example.
"""
payloadAttributeMappings: [AlertManagementPayloadAlertMappingField!]
"""
The example of an alert payload.
"""
payloadExample: JsonString
""" """
Token used to authenticate alert notification requests. Token used to authenticate alert notification requests.
""" """
...@@ -19086,6 +19101,31 @@ type Project { ...@@ -19086,6 +19101,31 @@ type Project {
statuses: [AlertManagementStatus!] statuses: [AlertManagementStatus!]
): AlertManagementAlertConnection ): AlertManagementAlertConnection
"""
HTTP Integrations which can receive alerts for the project.
"""
alertManagementHttpIntegrations(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
): AlertManagementHttpIntegrationConnection
""" """
Integrations which can receive alerts for the project. Integrations which can receive alerts for the project.
""" """
......
...@@ -1672,6 +1672,118 @@ ...@@ -1672,6 +1672,118 @@
"enumValues": null, "enumValues": null,
"possibleTypes": null "possibleTypes": null
}, },
{
"kind": "OBJECT",
"name": "AlertManagementHttpIntegrationConnection",
"description": "The connection type for AlertManagementHttpIntegration.",
"fields": [
{
"name": "edges",
"description": "A list of edges.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AlertManagementHttpIntegrationEdge",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": "A list of nodes.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AlertManagementHttpIntegration",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "Information to aid in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "PageInfo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "AlertManagementHttpIntegrationEdge",
"description": "An edge in a connection.",
"fields": [
{
"name": "cursor",
"description": "A cursor for use in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "node",
"description": "The item at the end of the edge.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "AlertManagementHttpIntegration",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{ {
"kind": "SCALAR", "kind": "SCALAR",
"name": "AlertManagementHttpIntegrationID", "name": "AlertManagementHttpIntegrationID",
...@@ -1747,42 +1859,6 @@ ...@@ -1747,42 +1859,6 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "payloadAttributeMappings",
"description": "The custom mapping of GitLab alert attributes to fields from the payload_example.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AlertManagementPayloadAlertMappingField",
"ofType": null
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "payloadExample",
"description": "The example of an alert payload.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "JsonString",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "token", "name": "token",
"description": "Token used to authenticate alert notification requests.", "description": "Token used to authenticate alert notification requests.",
...@@ -2357,42 +2433,6 @@ ...@@ -2357,42 +2433,6 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "payloadAttributeMappings",
"description": "The custom mapping of GitLab alert attributes to fields from the payload_example.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AlertManagementPayloadAlertMappingField",
"ofType": null
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "payloadExample",
"description": "The example of an alert payload.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "JsonString",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "token", "name": "token",
"description": "Token used to authenticate alert notification requests.", "description": "Token used to authenticate alert notification requests.",
...@@ -56049,6 +56089,59 @@ ...@@ -56049,6 +56089,59 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "alertManagementHttpIntegrations",
"description": "HTTP Integrations which can receive alerts for the project.",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "AlertManagementHttpIntegrationConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "alertManagementIntegrations", "name": "alertManagementIntegrations",
"description": "Integrations which can receive alerts for the project.", "description": "Integrations which can receive alerts for the project.",
...@@ -311,8 +311,6 @@ An endpoint and credentials used to accept Prometheus alerts for a project. ...@@ -311,8 +311,6 @@ An endpoint and credentials used to accept Prometheus alerts for a project.
| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard. | | `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard. |
| `id` | ID! | ID of the integration. | | `id` | ID! | ID of the integration. |
| `name` | String | Name of the integration. | | `name` | String | Name of the integration. |
| `payloadAttributeMappings` | AlertManagementPayloadAlertMappingField! => Array | The custom mapping of GitLab alert attributes to fields from the payload_example. |
| `payloadExample` | JsonString | The example of an alert payload. |
| `token` | String | Token used to authenticate alert notification requests. | | `token` | String | Token used to authenticate alert notification requests. |
| `type` | AlertManagementIntegrationType! | Type of integration. | | `type` | AlertManagementIntegrationType! | Type of integration. |
| `url` | String | Endpoint which accepts alert notifications. | | `url` | String | Endpoint which accepts alert notifications. |
...@@ -3043,6 +3041,7 @@ Autogenerated return type of PipelineRetry. ...@@ -3043,6 +3041,7 @@ Autogenerated return type of PipelineRetry.
| `alertManagementAlert` | AlertManagementAlert | A single Alert Management alert of the project. | | `alertManagementAlert` | AlertManagementAlert | A single Alert Management alert of the project. |
| `alertManagementAlertStatusCounts` | AlertManagementAlertStatusCountsType | Counts of alerts by status for the project. | | `alertManagementAlertStatusCounts` | AlertManagementAlertStatusCountsType | Counts of alerts by status for the project. |
| `alertManagementAlerts` | AlertManagementAlertConnection | Alert Management alerts of the project. | | `alertManagementAlerts` | AlertManagementAlertConnection | Alert Management alerts of the project. |
| `alertManagementHttpIntegrations` | AlertManagementHttpIntegrationConnection | HTTP Integrations which can receive alerts for the project. |
| `alertManagementIntegrations` | AlertManagementIntegrationConnection | Integrations which can receive alerts for the project. | | `alertManagementIntegrations` | AlertManagementIntegrationConnection | Integrations which can receive alerts for the project. |
| `alertManagementPayloadFields` | AlertManagementPayloadAlertField! => Array | Extract alert fields from payload for custom mapping. | | `alertManagementPayloadFields` | AlertManagementPayloadAlertField! => Array | Extract alert fields from payload for custom mapping. |
| `allowMergeOnSkippedPipeline` | Boolean | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs. | | `allowMergeOnSkippedPipeline` | Boolean | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs. |
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
module EE module EE
module Types module Types
module AlertManagement module AlertManagement
module IntegrationType module HttpIntegrationType
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do prepended do
field :payload_example, ::Types::JsonStringType, field :payload_example, ::Types::JsonStringType,
null: true, null: true,
description: 'The example of an alert payload.' description: 'The example of an alert payload.'
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['AlertManagementHttpIntegration'] do
specify { expect(described_class.graphql_name).to eq('AlertManagementHttpIntegration') }
specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
it 'exposes the expected fields' do
expected_fields = %i[
id
type
name
active
token
url
api_url
payload_example
payload_attribute_mappings
]
expect(described_class).to have_graphql_fields(*expected_fields)
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'getting Alert Management HTTP Integrations' do
include ::Gitlab::Routing.url_helpers
include GraphqlHelpers
let_it_be(:payload_example) do
{
alert: {
desc: 'Alert description',
name: 'Alert name'
}
}
end
let_it_be(:payload_attribute_mapping) do
{
title: { path: %w(alert name), type: 'string' },
description: { path: %w(alert desc), type: 'string', label: 'Description' }
}
end
let_it_be(:project) { create(:project, :repository) }
let_it_be(:current_user) { create(:user) }
let_it_be(:prometheus_service) { create(:prometheus_service, project: project) }
let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) }
let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) }
let_it_be(:other_project_http_integration) { create(:alert_management_http_integration) }
let_it_be(:active_http_integration) do
create(
:alert_management_http_integration,
project: project,
payload_example: payload_example,
payload_attribute_mapping: payload_attribute_mapping
)
end
let(:fields) do
<<~QUERY
nodes {
#{all_graphql_fields_for('AlertManagementHttpIntegration')}
}
QUERY
end
let(:query) do
graphql_query_for(
'project',
{ 'fullPath' => project.full_path },
query_graphql_field('alertManagementHttpIntegrations', {}, fields)
)
end
before do
stub_licensed_features(multiple_alert_http_integrations: true)
stub_feature_flags(multiple_http_integrations_custom_mapping: project)
end
context 'with integrations' do
let(:integrations) { graphql_data.dig('project', 'alertManagementHttpIntegrations', 'nodes') }
context 'without project permissions' do
let(:user) { create(:user) }
before do
post_graphql(query, current_user: current_user)
end
it_behaves_like 'a working graphql query'
specify { expect(integrations).to be_nil }
end
context 'with project permissions' do
before do
project.add_maintainer(current_user)
post_graphql(query, current_user: current_user)
end
it_behaves_like 'a working graphql query'
specify { expect(integrations.size).to eq(2) }
it 'returns the correct properties of the integrations' do
expect(integrations).to include(
{
'id' => GitlabSchema.id_from_object(active_http_integration).to_s,
'type' => 'HTTP',
'name' => active_http_integration.name,
'active' => active_http_integration.active,
'token' => active_http_integration.token,
'url' => active_http_integration.url,
'apiUrl' => nil,
'payloadExample' => payload_example.to_json,
'payloadAttributeMappings' => [
{
'fieldName' => 'TITLE',
'label' => nil,
'path' => %w(alert name),
'type' => 'STRING'
},
{
'fieldName' => 'DESCRIPTION',
'label' => 'Description',
'path' => %w(alert desc),
'type' => 'STRING'
}
]
},
{
'id' => GitlabSchema.id_from_object(inactive_http_integration).to_s,
'type' => 'HTTP',
'name' => inactive_http_integration.name,
'active' => inactive_http_integration.active,
'token' => inactive_http_integration.token,
'url' => inactive_http_integration.url,
'apiUrl' => nil,
'payloadExample' => "{}",
'payloadAttributeMappings' => []
}
)
end
end
end
end
...@@ -5,36 +5,13 @@ RSpec.describe 'getting Alert Management Integrations' do ...@@ -5,36 +5,13 @@ RSpec.describe 'getting Alert Management Integrations' do
include ::Gitlab::Routing.url_helpers include ::Gitlab::Routing.url_helpers
include GraphqlHelpers include GraphqlHelpers
let_it_be(:payload_example) do
{
alert: {
desc: 'Alert description',
name: 'Alert name'
}
}
end
let_it_be(:payload_attribute_mapping) do
{
title: { path: %w(alert name), type: 'string' },
description: { path: %w(alert desc), type: 'string', label: 'Description' }
}
end
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let_it_be(:prometheus_service) { create(:prometheus_service, project: project) } let_it_be(:prometheus_service) { create(:prometheus_service, project: project) }
let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) } let_it_be(:active_http_integration) { create(:alert_management_http_integration, project: project) }
let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) } let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) }
let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) }
let_it_be(:other_project_http_integration) { create(:alert_management_http_integration) } let_it_be(:other_project_http_integration) { create(:alert_management_http_integration) }
let_it_be(:active_http_integration) do
create(
:alert_management_http_integration,
project: project,
payload_example: payload_example,
payload_attribute_mapping: payload_attribute_mapping
)
end
let(:fields) do let(:fields) do
<<~QUERY <<~QUERY
...@@ -54,7 +31,6 @@ RSpec.describe 'getting Alert Management Integrations' do ...@@ -54,7 +31,6 @@ RSpec.describe 'getting Alert Management Integrations' do
before do before do
stub_licensed_features(multiple_alert_http_integrations: true) stub_licensed_features(multiple_alert_http_integrations: true)
stub_feature_flags(multiple_http_integrations_custom_mapping: project)
end end
context 'with integrations' do context 'with integrations' do
...@@ -91,22 +67,7 @@ RSpec.describe 'getting Alert Management Integrations' do ...@@ -91,22 +67,7 @@ RSpec.describe 'getting Alert Management Integrations' do
'active' => active_http_integration.active, 'active' => active_http_integration.active,
'token' => active_http_integration.token, 'token' => active_http_integration.token,
'url' => active_http_integration.url, 'url' => active_http_integration.url,
'apiUrl' => nil, 'apiUrl' => nil
'payloadExample' => payload_example.to_json,
'payloadAttributeMappings' => [
{
'fieldName' => 'TITLE',
'label' => nil,
'path' => %w(alert name),
'type' => 'STRING'
},
{
'fieldName' => 'DESCRIPTION',
'label' => 'Description',
'path' => %w(alert desc),
'type' => 'STRING'
}
]
}, },
{ {
'id' => GitlabSchema.id_from_object(inactive_http_integration).to_s, 'id' => GitlabSchema.id_from_object(inactive_http_integration).to_s,
...@@ -115,9 +76,7 @@ RSpec.describe 'getting Alert Management Integrations' do ...@@ -115,9 +76,7 @@ RSpec.describe 'getting Alert Management Integrations' do
'active' => inactive_http_integration.active, 'active' => inactive_http_integration.active,
'token' => inactive_http_integration.token, 'token' => inactive_http_integration.token,
'url' => inactive_http_integration.url, 'url' => inactive_http_integration.url,
'apiUrl' => nil, 'apiUrl' => nil
'payloadExample' => "{}",
'payloadAttributeMappings' => []
}, },
{ {
'id' => GitlabSchema.id_from_object(prometheus_service).to_s, 'id' => GitlabSchema.id_from_object(prometheus_service).to_s,
...@@ -126,9 +85,7 @@ RSpec.describe 'getting Alert Management Integrations' do ...@@ -126,9 +85,7 @@ RSpec.describe 'getting Alert Management Integrations' do
'active' => prometheus_service.manual_configuration?, 'active' => prometheus_service.manual_configuration?,
'token' => project_alerting_setting.token, 'token' => project_alerting_setting.token,
'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json", 'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json",
'apiUrl' => prometheus_service.api_url, 'apiUrl' => prometheus_service.api_url
'payloadExample' => "{}",
'payloadAttributeMappings' => []
} }
) )
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::AlertManagement::HttpIntegrationsResolver do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:prometheus_integration) { create(:prometheus_service, project: project) }
let_it_be(:active_http_integration) { create(:alert_management_http_integration, project: project) }
let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) }
let_it_be(:other_proj_integration) { create(:alert_management_http_integration) }
subject { sync(resolve_http_integrations) }
specify do
expect(described_class).to have_nullable_graphql_type(Types::AlertManagement::HttpIntegrationType.connection_type)
end
context 'user does not have permission' do
it { is_expected.to be_empty }
end
context 'user has permission' do
before do
project.add_maintainer(current_user)
end
it { is_expected.to contain_exactly(active_http_integration) }
end
private
def resolve_http_integrations(args = {}, context = { current_user: current_user })
resolve(described_class, obj: project, ctx: context)
end
end
...@@ -16,10 +16,6 @@ RSpec.describe GitlabSchema.types['AlertManagementIntegration'] do ...@@ -16,10 +16,6 @@ RSpec.describe GitlabSchema.types['AlertManagementIntegration'] do
api_url api_url
] ]
if Gitlab.ee?
expected_fields.push('payload_example', 'payload_attribute_mappings')
end
expect(described_class).to have_graphql_fields(*expected_fields) expect(described_class).to have_graphql_fields(*expected_fields)
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment