Skip to content

Commit 7a0b01c

Browse files
authored
Add methods to get and update organization integration configData (#80)
* Extend OrganizationIntegrationsService to support GET org integration details endpoint * Support variable shape configData for org integrations * Implement OrganizationIntegrationsService UpdateConfig
1 parent 97df7c9 commit 7a0b01c

File tree

2 files changed

+182
-9
lines changed

2 files changed

+182
-9
lines changed

sentry/organization_integrations.go

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,34 @@ type OrganizationIntegrationProvider struct {
1616
Features []string `json:"features"`
1717
}
1818

19+
// IntegrationConfigData for defining integration-specific configuration data.
20+
type IntegrationConfigData map[string]interface{}
21+
1922
// OrganizationIntegration represents an integration added for the organization.
2023
// https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/serializers/models/integration.py#L93
2124
type OrganizationIntegration struct {
2225
// https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/serializers/models/integration.py#L35
2326
ID string `json:"id"`
2427
Name string `json:"name"`
25-
Icon string `json:"icon"`
28+
Icon *string `json:"icon"`
2629
DomainName string `json:"domainName"`
27-
AccountType string `json:"accountType"`
30+
AccountType *string `json:"accountType"`
2831
Scopes []string `json:"scopes"`
2932
Status string `json:"status"`
3033
Provider OrganizationIntegrationProvider `json:"provider"`
3134

3235
// https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/serializers/models/integration.py#L138
33-
ExternalId string `json:"externalId"`
34-
OrganizationId int `json:"organizationId"`
35-
OrganizationIntegrationStatus string `json:"organizationIntegrationStatus"`
36-
GracePeriodEnd *time.Time `json:"gracePeriodEnd"`
36+
ConfigData *IntegrationConfigData `json:"configData"`
37+
ExternalId string `json:"externalId"`
38+
OrganizationId int `json:"organizationId"`
39+
OrganizationIntegrationStatus string `json:"organizationIntegrationStatus"`
40+
GracePeriodEnd *time.Time `json:"gracePeriodEnd"`
3741
}
3842

3943
// OrganizationIntegrationsService provides methods for accessing Sentry organization integrations API endpoints.
40-
// Paths: https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/urls.py#L1236-L1240
44+
// Paths: https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/urls.py#L1236-L1245
4145
// Endpoints: https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/endpoints/integrations/organization_integrations/index.py
46+
// Endpoints: https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/endpoints/integrations/organization_integrations/details.py
4247
type OrganizationIntegrationsService service
4348

4449
type ListOrganizationIntegrationsParams struct {
@@ -66,3 +71,33 @@ func (s *OrganizationIntegrationsService) List(ctx context.Context, organization
6671
}
6772
return integrations, resp, nil
6873
}
74+
75+
// Get organization integration details.
76+
func (s *OrganizationIntegrationsService) Get(ctx context.Context, organizationSlug string, integrationID string) (*OrganizationIntegration, *Response, error) {
77+
u := fmt.Sprintf("0/organizations/%v/integrations/%v/", organizationSlug, integrationID)
78+
req, err := s.client.NewRequest("GET", u, nil)
79+
if err != nil {
80+
return nil, nil, err
81+
}
82+
83+
integration := new(OrganizationIntegration)
84+
resp, err := s.client.Do(ctx, req, integration)
85+
if err != nil {
86+
return nil, resp, err
87+
}
88+
return integration, resp, nil
89+
}
90+
91+
type UpdateConfigOrganizationIntegrationsParams = IntegrationConfigData
92+
93+
// UpdateConfig - update configData for organization integration.
94+
// https://github.com/getsentry/sentry/blob/22.7.0/src/sentry/api/endpoints/integrations/organization_integrations/details.py#L94-L102
95+
func (s *OrganizationIntegrationsService) UpdateConfig(ctx context.Context, organizationSlug string, integrationID string, params *UpdateConfigOrganizationIntegrationsParams) (*Response, error) {
96+
u := fmt.Sprintf("0/organizations/%v/integrations/%v/", organizationSlug, integrationID)
97+
req, err := s.client.NewRequest("POST", u, params)
98+
if err != nil {
99+
return nil, err
100+
}
101+
102+
return s.client.Do(ctx, req, nil)
103+
}

sentry/organization_integrations_test.go

Lines changed: 140 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sentry
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67
"net/http"
78
"testing"
@@ -62,9 +63,9 @@ func TestOrganizationIntegrationsService_List(t *testing.T) {
6263
{
6364
ID: "123456",
6465
Name: "octocat",
65-
Icon: "https://avatars.githubusercontent.com/u/583231?v=4",
66+
Icon: String("https://avatars.githubusercontent.com/u/583231?v=4"),
6667
DomainName: "github.com/octocat",
67-
AccountType: "Organization",
68+
AccountType: String("Organization"),
6869
Scopes: []string{"read", "write"},
6970
Status: "active",
7071
Provider: OrganizationIntegrationProvider{
@@ -80,6 +81,7 @@ func TestOrganizationIntegrationsService_List(t *testing.T) {
8081
"stacktrace-link",
8182
},
8283
},
84+
ConfigData: &IntegrationConfigData{},
8385
ExternalId: "87654321",
8486
OrganizationId: 2,
8587
OrganizationIntegrationStatus: "active",
@@ -88,3 +90,139 @@ func TestOrganizationIntegrationsService_List(t *testing.T) {
8890
}
8991
assert.Equal(t, expected, integrations)
9092
}
93+
94+
func TestOrganizationIntegrationsService_Get(t *testing.T) {
95+
client, mux, _, teardown := setup()
96+
defer teardown()
97+
98+
mux.HandleFunc("/api/0/organizations/the-interstellar-jurisdiction/integrations/456789/", func(w http.ResponseWriter, r *http.Request) {
99+
assertMethod(t, "GET", r)
100+
w.Header().Set("Content-Type", "application/json")
101+
fmt.Fprint(w, `{
102+
"id": "456789",
103+
"name": "Interstellar PagerDuty",
104+
"icon": null,
105+
"domainName": "the-interstellar-jurisdiction",
106+
"accountType": null,
107+
"scopes": null,
108+
"status": "active",
109+
"provider": {
110+
"key": "pagerduty",
111+
"slug": "pagerduty",
112+
"name": "PagerDuty",
113+
"canAdd": true,
114+
"canDisable": false,
115+
"features": [
116+
"alert-rule",
117+
"incident-management"
118+
],
119+
"aspects": {
120+
"alerts": [
121+
{
122+
"type": "info",
123+
"text": "The PagerDuty integration adds a new Alert Rule action to all projects. To enable automatic notifications sent to PagerDuty you must create a rule using the PagerDuty action in your project settings."
124+
}
125+
]
126+
}
127+
},
128+
"configOrganization": [
129+
{
130+
"name": "service_table",
131+
"type": "table",
132+
"label": "PagerDuty services with the Sentry integration enabled",
133+
"help": "If services need to be updated, deleted, or added manually please do so here. Alert rules will need to be individually updated for any additions or deletions of services.",
134+
"addButtonText": "",
135+
"columnLabels": {
136+
"service": "Service",
137+
"integration_key": "Integration Key"
138+
},
139+
"columnKeys": [
140+
"service",
141+
"integration_key"
142+
],
143+
"confirmDeleteMessage": "Any alert rules associated with this service will stop working. The rules will still exist but will show a removed service."
144+
}
145+
],
146+
"configData": {
147+
"service_table": [
148+
{
149+
"service": "testing123",
150+
"integration_key": "abc123xyz",
151+
"id": 22222
152+
}
153+
]
154+
},
155+
"externalId": "999999",
156+
"organizationId": 2,
157+
"organizationIntegrationStatus": "active",
158+
"gracePeriodEnd": null
159+
}`)
160+
})
161+
162+
ctx := context.Background()
163+
integration, _, err := client.OrganizationIntegrations.Get(ctx, "the-interstellar-jurisdiction", "456789")
164+
assert.NoError(t, err)
165+
expected := OrganizationIntegration{
166+
ID: "456789",
167+
Name: "Interstellar PagerDuty",
168+
Icon: nil,
169+
DomainName: "the-interstellar-jurisdiction",
170+
AccountType: nil,
171+
Scopes: nil,
172+
Status: "active",
173+
Provider: OrganizationIntegrationProvider{
174+
Key: "pagerduty",
175+
Slug: "pagerduty",
176+
Name: "PagerDuty",
177+
CanAdd: true,
178+
CanDisable: false,
179+
Features: []string{
180+
"alert-rule",
181+
"incident-management",
182+
},
183+
},
184+
ConfigData: &IntegrationConfigData{
185+
"service_table": []interface{}{
186+
map[string]interface{}{
187+
"service": "testing123",
188+
"integration_key": "abc123xyz",
189+
"id": json.Number("22222"),
190+
},
191+
},
192+
},
193+
ExternalId: "999999",
194+
OrganizationId: 2,
195+
OrganizationIntegrationStatus: "active",
196+
GracePeriodEnd: nil,
197+
}
198+
assert.Equal(t, &expected, integration)
199+
}
200+
201+
func TestOrganizationIntegrationsService_UpdateConfig(t *testing.T) {
202+
client, mux, _, teardown := setup()
203+
defer teardown()
204+
205+
mux.HandleFunc("/api/0/organizations/the-interstellar-jurisdiction/integrations/456789/", func(w http.ResponseWriter, r *http.Request) {
206+
assertMethod(t, "POST", r)
207+
w.Header().Set("Content-Type", "application/json")
208+
})
209+
210+
updateConfigOrganizationIntegrationsParams := UpdateConfigOrganizationIntegrationsParams{
211+
"service_table": []interface{}{
212+
map[string]interface{}{
213+
"service": "testing123",
214+
"integration_key": "abc123xyz",
215+
"id": json.Number("22222"),
216+
},
217+
map[string]interface{}{
218+
"service": "testing456",
219+
"integration_key": "efg456lmn",
220+
"id": "",
221+
},
222+
},
223+
}
224+
ctx := context.Background()
225+
resp, err := client.OrganizationIntegrations.UpdateConfig(ctx, "the-interstellar-jurisdiction", "456789", &updateConfigOrganizationIntegrationsParams)
226+
assert.NoError(t, err)
227+
assert.Equal(t, int64(0), resp.ContentLength)
228+
}

0 commit comments

Comments
 (0)