Skip to content

Commit 1a1a2f3

Browse files
Plural Cloud CRUD (#1328)
Co-authored-by: Jake Laderman <[email protected]>
1 parent fdb8814 commit 1a1a2f3

File tree

57 files changed

+2192
-148
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2192
-148
lines changed

.github/workflows/daily.yml

-40
This file was deleted.

.github/workflows/firebase-hosting-pull-request.yml

-23
This file was deleted.

.github/workflows/test.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ jobs:
152152
curl -sL 'https://github.com/pluralsh/plural-cli/releases/download/v0.5.18/plural-cli_0.5.18_Linux_amd64.tar.gz' | tar xzvf -
153153
chmod +x plural
154154
cp plural /usr/local/bin/plural
155+
- run: make install-cockroach
155156
- run: make testup
156157
- name: Restore dependencies cache
157158
uses: actions/cache@v3

.github/workflows/www.yaml

+38-38
Original file line numberDiff line numberDiff line change
@@ -136,41 +136,41 @@ jobs:
136136
node-version: ${{ steps.engines.outputs.nodeVersion }}
137137
- run: yarn --immutable
138138
- run: yarn lint
139-
e2e:
140-
name: End-to-end test
141-
runs-on: ubuntu-20.04
142-
env:
143-
CYPRESS_EMAIL: ${{ secrets.CYPRESS_EMAIL }}
144-
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
145-
defaults:
146-
run:
147-
shell: bash
148-
working-directory: www
149-
steps:
150-
- name: 'Checkout'
151-
uses: actions/checkout@v3
152-
- name: Read Node.js version from package.json
153-
run: echo ::set-output name=nodeVersion::$(node -p "require('./package.json').engines.node")
154-
id: engines
155-
- name: 'Setup Node'
156-
uses: actions/setup-node@v3
157-
with:
158-
node-version: ${{ steps.engines.outputs.nodeVersion }}
159-
- run: yarn # Should run the --immutable in the CI by default
160-
- run: cd e2e && yarn
161-
- run: yarn e2e
162-
- uses: 8398a7/action-slack@v3
163-
if: failure()
164-
with:
165-
status: ${{ job.status }}
166-
fields: workflow,repo,commit,author,pullRequest
167-
env:
168-
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CYPRESS_WEBHOOK }}
169-
- name: Upload Screenshots and Videos to Slack
170-
if: failure()
171-
uses: trymbill/[email protected]
172-
with:
173-
token: ${{ secrets.SLACK_CYPRESS_TOKEN }}
174-
workdir: www/e2e/cypress
175-
channels: cypress-artifacts
176-
message-text: "See the attached videos and screenshots for more information."
139+
# e2e:
140+
# name: End-to-end test
141+
# runs-on: ubuntu-20.04
142+
# env:
143+
# CYPRESS_EMAIL: ${{ secrets.CYPRESS_EMAIL }}
144+
# CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
145+
# defaults:
146+
# run:
147+
# shell: bash
148+
# working-directory: www
149+
# steps:
150+
# - name: 'Checkout'
151+
# uses: actions/checkout@v3
152+
# - name: Read Node.js version from package.json
153+
# run: echo ::set-output name=nodeVersion::$(node -p "require('./package.json').engines.node")
154+
# id: engines
155+
# - name: 'Setup Node'
156+
# uses: actions/setup-node@v3
157+
# with:
158+
# node-version: ${{ steps.engines.outputs.nodeVersion }}
159+
# - run: yarn # Should run the --immutable in the CI by default
160+
# - run: cd e2e && yarn
161+
# - run: yarn e2e
162+
# - uses: 8398a7/action-slack@v3
163+
# if: failure()
164+
# with:
165+
# status: ${{ job.status }}
166+
# fields: workflow,repo,commit,author,pullRequest
167+
# env:
168+
# SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CYPRESS_WEBHOOK }}
169+
# - name: Upload Screenshots and Videos to Slack
170+
# if: failure()
171+
# uses: trymbill/[email protected]
172+
# with:
173+
# token: ${{ secrets.SLACK_CYPRESS_TOKEN }}
174+
# workdir: www/e2e/cypress
175+
# channels: cypress-artifacts
176+
# message-text: "See the attached videos and screenshots for more information."

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,7 @@ yarn-error.log*
6767
cert.pem
6868
key.pem
6969

70+
71+
/test-certs/
72+
7073
.vscode

.tool-versions

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
erlang 24.3.4.14
2-
elixir 1.12.3
1+
erlang 24.3.4.17
2+
elixir 1.13.4

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM bitwalker/alpine-elixir:1.12.3 AS builder
1+
FROM bitwalker/alpine-elixir:1.13.4 AS builder
22

33
# The following are build arguments used to change variable parts of the image.
44
# The name of your application/release (required)

Makefile

+19-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ DKR_HOST ?= dkr.plural.sh
88
dep ?= forge-core
99
GIT_COMMIT ?= abe123
1010
TARGETARCH ?= amd64
11+
COCKROACH_VSN ?= v24.1.3
1112

1213
help:
1314
@perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
@@ -48,11 +49,26 @@ else
4849
docker push $(DKR_HOST)/plural/${APP_NAME}:$(APP_VSN)
4950
endif
5051

51-
testup: ## sets up dependent services for test
52-
docker-compose up -d
52+
install-cockroach:
53+
sudo curl https://binaries.cockroachdb.com/cockroach-$(COCKROACH_VSN).linux-amd64.tgz | tar -xz && \
54+
sudo cp -i cockroach-$(COCKROACH_VSN).linux-amd64/cockroach /usr/local/bin/ && \
55+
sudo mkdir -p /usr/local/lib/cockroach && \
56+
sudo cp -i cockroach-$(COCKROACH_VSN).linux-amd64/lib/libgeos.so /usr/local/lib/cockroach/ && \
57+
sudo cp -i cockroach-$(COCKROACH_VSN).linux-amd64/lib/libgeos_c.so /usr/local/lib/cockroach/ && \
58+
cockroach version
59+
60+
test-certs:
61+
mkdir test-certs && \
62+
cockroach cert create-ca --certs-dir test-certs --ca-key test-certs/ca.key && \
63+
cockroach cert create-node localhost 127.0.0.1 --certs-dir test-certs --ca-key test-certs/ca.key && \
64+
cockroach cert create-client root --certs-dir test-certs --ca-key test-certs/ca.key && \
65+
cockroach cert list --certs-dir test-certs
66+
67+
testup: test-certs ## sets up dependent services for test
68+
docker compose up -d
5369

5470
testdown: ## tear down test dependencies
55-
docker-compose down
71+
docker compose down
5672

5773
connectdb: ## proxies the db in kubernetes via kubectl
5874
@echo "run psql -U forge -h 127.0.0.1 forge to connect"

apps/core/lib/core/clients/console.ex

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
defmodule Core.Clients.Console do
2+
require Logger
3+
4+
@clusters_q """
5+
query {
6+
clusters(first: 100) {
7+
edges { node { name id distro metadata } }
8+
}
9+
}
10+
"""
11+
12+
@create_svc_q """
13+
mutation Create($clusterId: ID!, $attributes: ServiceDeploymentAttributes!) {
14+
createServiceDeployment(clusterId: $clusterId, attributes: $attributes) {
15+
id
16+
}
17+
}
18+
"""
19+
20+
@delete_svc_q """
21+
mutation Delete($id: ID!) {
22+
deleteServiceDeployment(id: $id) {
23+
id
24+
}
25+
}
26+
"""
27+
28+
@update_svc_q """
29+
mutation Update($id: ID!, $attributes: ServiceUpdateAttributes!) {
30+
updateServiceDeployment(id: $id) {
31+
id
32+
}
33+
}
34+
"""
35+
36+
@repo_q """
37+
query Repo($url: String!) {
38+
gitRepository(url: $url) {
39+
id
40+
}
41+
}
42+
"""
43+
44+
def new(url, token) do
45+
Req.new(base_url: url, auth: "Token #{token}")
46+
|> AbsintheClient.attach()
47+
end
48+
49+
def clusters(client) do
50+
Req.post(client, graphql: @clusters_q)
51+
|> case do
52+
{:ok, %Req.Response{body: %{"clusters" => %{"edges" => edges}}}} -> {:ok, Enum.map(edges, & &1["node"])}
53+
res ->
54+
Logger.warn "Failed to fetch clusters: #{inspect(res)}"
55+
{:error, "could not fetch clusters"}
56+
end
57+
end
58+
59+
def repo(client, url) do
60+
Req.post(client, graphql: {@repo_q, %{url: url}})
61+
|> case do
62+
{:ok, %Req.Response{body: %{"gitRepository" => %{"id" => id}}}} -> {:ok, id}
63+
res ->
64+
Logger.warn "Failed to fetch clusters: #{inspect(res)}"
65+
{:error, "could not fetch repo"}
66+
end
67+
end
68+
69+
def create_service(client, cluster_id, attrs) do
70+
Req.post(client, graphql: {@create_svc_q, %{clusterId: cluster_id, attributes: attrs}})
71+
|> service_resp("createServiceDeployment")
72+
end
73+
74+
def update_service(client, id, attrs) do
75+
Req.post(client, graphql: {@update_svc_q, %{id: id, attributes: attrs}})
76+
|> service_resp("updateServiceDeployment")
77+
end
78+
79+
def delete_service(client, id) do
80+
Req.post(client, graphql: {@delete_svc_q, %{id: id}})
81+
|> service_resp("deleteServiceDeployment")
82+
end
83+
84+
defp service_resp({:ok, %Req.Response{status: 200, body: body}}, field) do
85+
case body[field] do
86+
%{"id" => id} -> {:ok, id}
87+
err ->
88+
Logger.warn "invalid console gql response: #{inspect(err)}"
89+
end
90+
end
91+
92+
defp service_resp(resp, _) do
93+
Logger.error "failed to fetch from console: #{inspect(resp)}"
94+
{:error, "console error"}
95+
end
96+
end

apps/core/lib/core/conduit/base.ex

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ defmodule Core.Conduit.Base do
1313
defqueue "plural.upgrade"
1414
defqueue "plural.scan"
1515
defqueue "plural.cluster"
16+
defqueue "plural.cloud"
1617
end
1718

1819
pipeline :out_tracking do
@@ -36,6 +37,7 @@ defmodule Core.Conduit.Base do
3637
publish :upgrade, exchange: "plural.topic", to: "plural.upgrade"
3738
publish :scan, exchange: "plural.topic", to: "plural.scan"
3839
publish :cluster, exchange: "plural.topic", to: "plural.cluster"
40+
publish :cloud, exchange: "plural.topic", to: "plural.cloud"
3941
end
4042

4143
outgoing do

apps/core/lib/core/policies/cloud.ex

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
defmodule Core.Policies.Cloud do
2+
use Piazza.Policy
3+
alias Core.Schema.{User, ConsoleInstance}
4+
alias Core.Services.Payments
5+
6+
def can?(%User{} = user, %ConsoleInstance{}, :create) do
7+
case Payments.has_feature?(user, :cd) do
8+
true -> :pass
9+
_ -> {:error, "you must be on a paid plan to use Plural Cloud"}
10+
end
11+
end
12+
13+
def can?(u, %Ecto.Changeset{} = cs, action), do: can?(u, apply_changes(cs), action)
14+
15+
def can?(_, _, _), do: :pass
16+
end

apps/core/lib/core/pubsub/events.ex

+5
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,8 @@ defmodule Core.PubSub.ClusterDependencyCreated, do: use Piazza.PubSub.Event
9090
defmodule Core.PubSub.DeferredUpdateCreated, do: use Piazza.PubSub.Event
9191

9292
defmodule Core.PubSub.UpgradesPromoted, do: use Piazza.PubSub.Event
93+
94+
defmodule Core.PubSub.ConsoleInstanceCreated, do: use Piazza.PubSub.Event
95+
defmodule Core.PubSub.ConsoleInstanceUpdated, do: use Piazza.PubSub.Event
96+
defmodule Core.PubSub.ConsoleInstanceDeleted, do: use Piazza.PubSub.Event
97+
defmodule Core.PubSub.ConsoleInstanceReaped, do: use Piazza.PubSub.Event

apps/core/lib/core/pubsub/protocols/fanout.ex

+11
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,14 @@ defimpl Core.PubSub.Fanout, for: [Core.PubSub.RoleCreated, Core.PubSub.RoleUpdat
235235
|> Enum.count()
236236
end
237237
end
238+
239+
defimpl Core.PubSub.Fanout, for: [
240+
Core.PubSub.ConsoleInstanceCreated,
241+
Core.PubSub.ConsoleInstanceUpdated,
242+
Core.PubSub.ConsoleInstanceDeleted
243+
] do
244+
def fanout(event) do
245+
%Conduit.Message{body: event}
246+
|> Core.Conduit.Broker.publish(:cloud)
247+
end
248+
end

0 commit comments

Comments
 (0)