Skip to content

Commit

Permalink
Merge branch 'release/0.29.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Christoph Pröschel committed Aug 25, 2021
2 parents 6f8a765 + 6985768 commit 4be4987
Show file tree
Hide file tree
Showing 190 changed files with 5,556 additions and 2,075 deletions.
21 changes: 13 additions & 8 deletions .github/ISSUE_TEMPLATE/---bug-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,32 @@ labels: bug
assignees: ""
---

**Describe the bug**
## Describe the bug

A clear and concise description of what the bug is.

**To Reproduce**
## To Reproduce

Steps to reproduce the behavior:

1. I installed Airy using '...'
2. When I ran command / did this in the UI
3. See error

**Expected behavior**
## Expected behavior

A clear and concise description of what you expected to happen.

**Screenshots**
## Screenshots

If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
## Environment

- OS: [e.g. iOS]
- Browser [e.g. Chrome, Safari]
- Version [e.g. 22]
- Browser: [e.g. Chrome, Safari]
- Version: [e.g. 22]

## Additional context

**Additional context**
Add any other context about the problem here.
12 changes: 8 additions & 4 deletions .github/ISSUE_TEMPLATE/---feature-request.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ labels: feature, needs discussion
assignees: ""
---

**Is your feature request related to a problem? Please describe.**
## Is your feature request related to a problem? Please describe.

A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
## Describe the solution you'd like

A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
## Describe alternatives you've considered

A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
## Additional context

Add any other context or screenshots about the feature request here.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.28.1
0.29.0
4 changes: 2 additions & 2 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
# Airy Bazel tools
git_repository(
name = "com_github_airyhq_bazel_tools",
commit = "2b34bc2b2c6fed64e4bb223d4624e06eda390e4d",
commit = "583a2e52c6941945ab5934585d5df8fff61b112f",
remote = "https://github.com/airyhq/bazel-tools.git",
shallow_since = "1625065439 +0200",
shallow_since = "1629796332 +0200",
)

load("@com_github_airyhq_bazel_tools//:repositories.bzl", "airy_bazel_tools_dependencies", "airy_jvm_deps")
Expand Down
1 change: 1 addition & 0 deletions backend/api/admin/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ app_deps = [
"//backend:webhook",
"//backend/model/metadata",
"//backend/model/template",
"//backend/model/event",
"//lib/java/uuid",
"//lib/java/spring/auth:spring-auth",
"//lib/java/spring/web:spring-web",
Expand Down
24 changes: 12 additions & 12 deletions backend/api/admin/src/main/java/co/airy/core/api/admin/Stores.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,9 @@ public class Stores implements HealthIndicator, ApplicationListener<ApplicationS

private final String connectedChannelsStore = "connected-channels-store";
private final String tagsStore = "tags-store";
private final String webhooksStore = "webhook-store";
private final String webhooksStore = "webhooks-store";
private final String templatesStore = "templates-store";

// Using a UUID as the default key for the webhook will make it easier
// to add multiple webhooks if that ever becomes a requirement
private final String allWebhooksKey = "339ab777-92aa-43a5-b452-82e73c50fc59";

private final String applicationCommunicationChannels = new ApplicationCommunicationChannels().name();
private final String applicationCommunicationWebhooks = new ApplicationCommunicationWebhooks().name();
private final String applicationCommunicationTags = new ApplicationCommunicationTags().name();
Expand All @@ -79,9 +75,7 @@ public void onApplicationEvent(ApplicationStartedEvent event) {
.filter((k, v) -> v.getConnectionState().equals(ChannelConnectionState.CONNECTED))
.leftJoin(metadataTable, ChannelContainer::new, Materialized.as(connectedChannelsStore));

builder.<String, Webhook>stream(applicationCommunicationWebhooks)
.groupBy((webhookId, webhook) -> allWebhooksKey)
.reduce((oldValue, newValue) -> newValue, Materialized.as(webhooksStore));
builder.<String, Webhook>table(applicationCommunicationWebhooks, Materialized.as(webhooksStore));

builder.<String, Tag>table(applicationCommunicationTags, Materialized.as(tagsStore));

Expand All @@ -99,8 +93,7 @@ public ReadOnlyKeyValueStore<String, Tag> getTagsStore() {
}

public void storeWebhook(Webhook webhook) throws ExecutionException, InterruptedException {
webhook.setId(allWebhooksKey);
producer.send(new ProducerRecord<>(applicationCommunicationWebhooks, allWebhooksKey, webhook)).get();
producer.send(new ProducerRecord<>(applicationCommunicationWebhooks, webhook.getId(), webhook)).get();
}

public void storeChannelContainer(ChannelContainer container) throws ExecutionException, InterruptedException {
Expand Down Expand Up @@ -172,9 +165,16 @@ public List<Template> getTemplates() {
return templates;
}

public Webhook getWebhook() {
public Webhook getWebhook(String webhookId) {
final ReadOnlyKeyValueStore<String, Webhook> webhookStore = getWebhookStore();
return webhookStore.get(allWebhooksKey);
return webhookStore.get(webhookId);
}

public List<Webhook> getWebhooks() {
final KeyValueIterator<String, Webhook> iterator = getWebhookStore().all();
List<Webhook> webhooks = new ArrayList<>();
iterator.forEachRemaining(kv -> webhooks.add(kv.value));
return webhooks;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,29 @@

import co.airy.avro.communication.Status;
import co.airy.avro.communication.Webhook;
import co.airy.core.api.admin.payload.GetWebhookResponse;
import co.airy.core.api.admin.payload.WebhookSubscriptionPayload;
import co.airy.core.api.admin.payload.WebhookListResponsePayload;
import co.airy.core.api.admin.payload.WebhookResponsePayload;
import co.airy.core.api.admin.payload.WebhookInfoRequestPayload;
import co.airy.core.api.admin.payload.WebhookSubscribePayload;
import co.airy.core.api.admin.payload.WebhookUnsubscribePayload;
import co.airy.core.api.config.ServiceDiscovery;
import co.airy.core.api.config.dto.ComponentInfo;
import co.airy.model.event.payload.EventType;
import co.airy.spring.web.payload.RequestErrorResponsePayload;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

@RestController
public class WebhooksController {
Expand All @@ -28,7 +37,7 @@ public WebhooksController(Stores stores, ServiceDiscovery serviceDiscovery) {
}

@PostMapping("/webhooks.subscribe")
public ResponseEntity<?> subscribe(@RequestBody @Valid WebhookSubscriptionPayload payload) {
public ResponseEntity<?> subscribe(@RequestBody @Valid WebhookSubscribePayload payload) {
final ComponentInfo component = serviceDiscovery.getComponent("integration-webhook");
if (component == null || !component.isEnabled()) {
return ResponseEntity.status(HttpStatus.CONFLICT)
Expand All @@ -39,11 +48,16 @@ public ResponseEntity<?> subscribe(@RequestBody @Valid WebhookSubscriptionPayloa
.body(new RequestErrorResponsePayload("The webhook component is enabled, but not healthy. Check the Kubernetes cluster state."));
}

final UUID id = Optional.ofNullable(payload.getId()).orElse(UUID.randomUUID());

final Webhook webhook = Webhook.newBuilder()
.setId(UUID.randomUUID().toString())
.setEndpoint(payload.getUrl())
.setId(id.toString())
.setEvents(payload.getEvents().stream().map(EventType::getEventType).collect(Collectors.toList()))
.setEndpoint(payload.getUrl().toString())
.setStatus(Status.Subscribed)
.setHeaders(payload.getHeaders())
.setSignKey(payload.getSignatureKey())
.setSubscribedAt(Instant.now().toEpochMilli())
.build();

try {
Expand All @@ -56,11 +70,13 @@ public ResponseEntity<?> subscribe(@RequestBody @Valid WebhookSubscriptionPayloa
}

@PostMapping("/webhooks.unsubscribe")
public ResponseEntity<?> unsubscribe() {
Webhook webhook = stores.getWebhook();

public ResponseEntity<?> unsubscribe(@RequestBody @Valid WebhookUnsubscribePayload payload) {
Webhook webhook = stores.getWebhook(payload.getId().toString());
if (webhook == null) {
return ResponseEntity.ok().build();
return ResponseEntity.notFound().build();
}
if (webhook.getStatus().equals(Status.Unsubscribed)) {
return ResponseEntity.status(HttpStatus.OK).body(fromWebhook(webhook));
}

webhook.setStatus(Status.Unsubscribed);
Expand All @@ -75,18 +91,25 @@ public ResponseEntity<?> unsubscribe() {
}

@PostMapping("/webhooks.info")
public ResponseEntity<GetWebhookResponse> webhookInfo() {
final Webhook webhook = stores.getWebhook();

public ResponseEntity<WebhookResponsePayload> webhookInfo(@RequestBody @Valid WebhookInfoRequestPayload payload) {
final Webhook webhook = stores.getWebhook(payload.getId().toString());
if (webhook == null) {
return ResponseEntity.notFound().build();
}

return ResponseEntity.status(HttpStatus.OK).body(fromWebhook(webhook));
}

private GetWebhookResponse fromWebhook(Webhook webhook) {
return GetWebhookResponse.builder()
@PostMapping("/webhooks.list")
public ResponseEntity<WebhookListResponsePayload> webhookList() {
final List<WebhookResponsePayload> webhooks = stores.getWebhooks().stream().map(this::fromWebhook).collect(Collectors.toList());
return ResponseEntity.status(HttpStatus.OK).body(new WebhookListResponsePayload(webhooks));
}

private WebhookResponsePayload fromWebhook(Webhook webhook) {
return WebhookResponsePayload.builder()
.id(webhook.getId())
.events(webhook.getEvents())
.headers(webhook.getHeaders())
.status(webhook.getStatus().toString())
.url(webhook.getEndpoint())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package co.airy.core.api.admin.payload;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotNull;
import java.util.UUID;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WebhookInfoRequestPayload {
@NotNull
private UUID id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package co.airy.core.api.admin.payload;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class WebhookListResponsePayload {
private List<WebhookResponsePayload> data;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
import lombok.Builder;
import lombok.Data;

import java.util.List;
import java.util.Map;

@Data
@Builder
public class GetWebhookResponse {
public class WebhookResponsePayload {
private String id;
private String name;
private String status;
private String url;
private Map<String, String> headers;
private List<String> events;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package co.airy.core.api.admin.payload;

import co.airy.model.event.payload.EventType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotNull;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class WebhookSubscribePayload {
private UUID id;
@NotNull
private URI url;
private Map<String, String> headers = new HashMap<>();
private List<EventType> events = new ArrayList<>();
private String signatureKey;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class WebhookSubscriptionPayload {
private Map<String, String> headers = new HashMap<>();

public class WebhookUnsubscribePayload {
@NotNull
private String url;
private UUID id;
}
Loading

0 comments on commit 4be4987

Please sign in to comment.