mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
feat: add tables for PGCoordinator v2 (#10442)
Adds tables for a simplified PG Coordinator that only considers Peers and Tunnels, rather than agent/client distinctions we have today.
This commit is contained in:
67
coderd/database/dump.sql
generated
67
coderd/database/dump.sql
generated
@ -141,6 +141,11 @@ CREATE TYPE startup_script_behavior AS ENUM (
|
||||
'non-blocking'
|
||||
);
|
||||
|
||||
CREATE TYPE tailnet_status AS ENUM (
|
||||
'ok',
|
||||
'lost'
|
||||
);
|
||||
|
||||
CREATE TYPE user_status AS ENUM (
|
||||
'active',
|
||||
'suspended',
|
||||
@ -292,6 +297,35 @@ BEGIN
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION tailnet_notify_peer_change() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF (OLD IS NOT NULL) THEN
|
||||
PERFORM pg_notify('tailnet_peer_update', OLD.id::text);
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
IF (NEW IS NOT NULL) THEN
|
||||
PERFORM pg_notify('tailnet_peer_update', NEW.id::text);
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION tailnet_notify_tunnel_change() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF (NEW IS NOT NULL) THEN
|
||||
PERFORM pg_notify('tailnet_tunnel_update', NEW.src_id || ',' || NEW.dst_id);
|
||||
RETURN NULL;
|
||||
ELSIF (OLD IS NOT NULL) THEN
|
||||
PERFORM pg_notify('tailnet_tunnel_update', OLD.src_id || ',' || OLD.dst_id);
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE TABLE api_keys (
|
||||
id text NOT NULL,
|
||||
hashed_secret bytea NOT NULL,
|
||||
@ -587,6 +621,21 @@ CREATE TABLE tailnet_coordinators (
|
||||
|
||||
COMMENT ON TABLE tailnet_coordinators IS 'We keep this separate from replicas in case we need to break the coordinator out into its own service';
|
||||
|
||||
CREATE TABLE tailnet_peers (
|
||||
id uuid NOT NULL,
|
||||
coordinator_id uuid NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
node bytea NOT NULL,
|
||||
status tailnet_status DEFAULT 'ok'::tailnet_status NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE tailnet_tunnels (
|
||||
coordinator_id uuid NOT NULL,
|
||||
src_id uuid NOT NULL,
|
||||
dst_id uuid NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE template_version_parameters (
|
||||
template_version_id uuid NOT NULL,
|
||||
name text NOT NULL,
|
||||
@ -1248,6 +1297,12 @@ ALTER TABLE ONLY tailnet_clients
|
||||
ALTER TABLE ONLY tailnet_coordinators
|
||||
ADD CONSTRAINT tailnet_coordinators_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY tailnet_peers
|
||||
ADD CONSTRAINT tailnet_peers_pkey PRIMARY KEY (id, coordinator_id);
|
||||
|
||||
ALTER TABLE ONLY tailnet_tunnels
|
||||
ADD CONSTRAINT tailnet_tunnels_pkey PRIMARY KEY (coordinator_id, src_id, dst_id);
|
||||
|
||||
ALTER TABLE ONLY template_version_parameters
|
||||
ADD CONSTRAINT template_version_parameters_template_version_id_name_key UNIQUE (template_version_id, name);
|
||||
|
||||
@ -1351,6 +1406,8 @@ CREATE INDEX idx_tailnet_agents_coordinator ON tailnet_agents USING btree (coord
|
||||
|
||||
CREATE INDEX idx_tailnet_clients_coordinator ON tailnet_clients USING btree (coordinator_id);
|
||||
|
||||
CREATE INDEX idx_tailnet_peers_coordinator ON tailnet_peers USING btree (coordinator_id);
|
||||
|
||||
CREATE UNIQUE INDEX idx_users_email ON users USING btree (email) WHERE (deleted = false);
|
||||
|
||||
CREATE UNIQUE INDEX idx_users_username ON users USING btree (username) WHERE (deleted = false);
|
||||
@ -1391,6 +1448,10 @@ CREATE TRIGGER tailnet_notify_client_subscription_change AFTER INSERT OR DELETE
|
||||
|
||||
CREATE TRIGGER tailnet_notify_coordinator_heartbeat AFTER INSERT OR UPDATE ON tailnet_coordinators FOR EACH ROW EXECUTE FUNCTION tailnet_notify_coordinator_heartbeat();
|
||||
|
||||
CREATE TRIGGER tailnet_notify_peer_change AFTER INSERT OR DELETE OR UPDATE ON tailnet_peers FOR EACH ROW EXECUTE FUNCTION tailnet_notify_peer_change();
|
||||
|
||||
CREATE TRIGGER tailnet_notify_tunnel_change AFTER INSERT OR DELETE OR UPDATE ON tailnet_tunnels FOR EACH ROW EXECUTE FUNCTION tailnet_notify_tunnel_change();
|
||||
|
||||
CREATE TRIGGER trigger_insert_apikeys BEFORE INSERT ON api_keys FOR EACH ROW EXECUTE FUNCTION insert_apikey_fail_if_user_deleted();
|
||||
|
||||
CREATE TRIGGER trigger_update_users AFTER INSERT OR UPDATE ON users FOR EACH ROW WHEN ((new.deleted = true)) EXECUTE FUNCTION delete_deleted_user_api_keys();
|
||||
@ -1440,6 +1501,12 @@ ALTER TABLE ONLY tailnet_client_subscriptions
|
||||
ALTER TABLE ONLY tailnet_clients
|
||||
ADD CONSTRAINT tailnet_clients_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY tailnet_peers
|
||||
ADD CONSTRAINT tailnet_peers_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY tailnet_tunnels
|
||||
ADD CONSTRAINT tailnet_tunnels_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY template_version_parameters
|
||||
ADD CONSTRAINT template_version_parameters_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
|
||||
|
@ -21,6 +21,8 @@ const (
|
||||
ForeignKeyTailnetAgentsCoordinatorID ForeignKeyConstraint = "tailnet_agents_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_agents ADD CONSTRAINT tailnet_agents_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTailnetClientSubscriptionsCoordinatorID ForeignKeyConstraint = "tailnet_client_subscriptions_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_client_subscriptions ADD CONSTRAINT tailnet_client_subscriptions_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTailnetClientsCoordinatorID ForeignKeyConstraint = "tailnet_clients_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_clients ADD CONSTRAINT tailnet_clients_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTailnetPeersCoordinatorID ForeignKeyConstraint = "tailnet_peers_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_peers ADD CONSTRAINT tailnet_peers_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTailnetTunnelsCoordinatorID ForeignKeyConstraint = "tailnet_tunnels_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_tunnels ADD CONSTRAINT tailnet_tunnels_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionParametersTemplateVersionID ForeignKeyConstraint = "template_version_parameters_template_version_id_fkey" // ALTER TABLE ONLY template_version_parameters ADD CONSTRAINT template_version_parameters_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionVariablesTemplateVersionID ForeignKeyConstraint = "template_version_variables_template_version_id_fkey" // ALTER TABLE ONLY template_version_variables ADD CONSTRAINT template_version_variables_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionsCreatedBy ForeignKeyConstraint = "template_versions_created_by_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
|
@ -0,0 +1,14 @@
|
||||
BEGIN;
|
||||
|
||||
DROP TRIGGER IF EXISTS tailnet_notify_tunnel_change ON tailnet_tunnels;
|
||||
DROP FUNCTION IF EXISTS tailnet_notify_tunnel_change;
|
||||
DROP TABLE IF EXISTS tailnet_tunnels;
|
||||
|
||||
DROP TRIGGER IF EXISTS tailnet_notify_peer_change ON tailnet_peers;
|
||||
DROP FUNCTION IF EXISTS tailnet_notify_peer_change;
|
||||
DROP INDEX IF EXISTS idx_tailnet_peers_coordinator;
|
||||
DROP TABLE IF EXISTS tailnet_peers;
|
||||
|
||||
DROP TYPE IF EXISTS tailnet_status;
|
||||
|
||||
COMMIT;
|
@ -0,0 +1,72 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE TYPE tailnet_status AS ENUM (
|
||||
'ok',
|
||||
'lost'
|
||||
);
|
||||
|
||||
CREATE TABLE tailnet_peers (
|
||||
id uuid NOT NULL,
|
||||
coordinator_id uuid NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
node bytea NOT NULL,
|
||||
status tailnet_status DEFAULT 'ok'::tailnet_status NOT NULL,
|
||||
PRIMARY KEY (id, coordinator_id),
|
||||
FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- For shutting down / GC a coordinator
|
||||
CREATE INDEX idx_tailnet_peers_coordinator ON tailnet_peers (coordinator_id);
|
||||
|
||||
-- Any time tailnet_peers table changes, send an update with the affected peer ID.
|
||||
CREATE FUNCTION tailnet_notify_peer_change() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF (OLD IS NOT NULL) THEN
|
||||
PERFORM pg_notify('tailnet_peer_update', OLD.id::text);
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
IF (NEW IS NOT NULL) THEN
|
||||
PERFORM pg_notify('tailnet_peer_update', NEW.id::text);
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER tailnet_notify_peer_change
|
||||
AFTER INSERT OR UPDATE OR DELETE ON tailnet_peers
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE tailnet_notify_peer_change();
|
||||
|
||||
CREATE TABLE tailnet_tunnels (
|
||||
coordinator_id uuid NOT NULL,
|
||||
-- we don't keep foreign keys for src_id and dst_id because the coordinator doesn't
|
||||
-- strictly order creating the peers and creating the tunnels
|
||||
src_id uuid NOT NULL,
|
||||
dst_id uuid NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY (coordinator_id, src_id, dst_id),
|
||||
FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE FUNCTION tailnet_notify_tunnel_change() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF (NEW IS NOT NULL) THEN
|
||||
PERFORM pg_notify('tailnet_tunnel_update', NEW.src_id || ',' || NEW.dst_id);
|
||||
RETURN NULL;
|
||||
ELSIF (OLD IS NOT NULL) THEN
|
||||
PERFORM pg_notify('tailnet_tunnel_update', OLD.src_id || ',' || OLD.dst_id);
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER tailnet_notify_tunnel_change
|
||||
AFTER INSERT OR UPDATE OR DELETE ON tailnet_tunnels
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE tailnet_notify_tunnel_change();
|
||||
|
||||
COMMIT;
|
18
coderd/database/migrations/testdata/fixtures/000168_pg_coord_tailnet_v2_api.up.sql
vendored
Normal file
18
coderd/database/migrations/testdata/fixtures/000168_pg_coord_tailnet_v2_api.up.sql
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
INSERT INTO tailnet_peers
|
||||
(id, coordinator_id, updated_at, node, status)
|
||||
VALUES (
|
||||
'c0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
||||
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
||||
'2023-06-15 10:23:54+00',
|
||||
'a fake protobuf byte string',
|
||||
'ok'
|
||||
);
|
||||
|
||||
INSERT INTO tailnet_tunnels
|
||||
(coordinator_id, src_id, dst_id, updated_at)
|
||||
VALUES (
|
||||
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
||||
'c0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
||||
'b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
||||
'2023-06-15 10:23:54+00'
|
||||
);
|
@ -1289,6 +1289,64 @@ func AllStartupScriptBehaviorValues() []StartupScriptBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
type TailnetStatus string
|
||||
|
||||
const (
|
||||
TailnetStatusOk TailnetStatus = "ok"
|
||||
TailnetStatusLost TailnetStatus = "lost"
|
||||
)
|
||||
|
||||
func (e *TailnetStatus) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = TailnetStatus(s)
|
||||
case string:
|
||||
*e = TailnetStatus(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for TailnetStatus: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullTailnetStatus struct {
|
||||
TailnetStatus TailnetStatus `json:"tailnet_status"`
|
||||
Valid bool `json:"valid"` // Valid is true if TailnetStatus is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullTailnetStatus) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.TailnetStatus, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.TailnetStatus.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullTailnetStatus) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.TailnetStatus), nil
|
||||
}
|
||||
|
||||
func (e TailnetStatus) Valid() bool {
|
||||
switch e {
|
||||
case TailnetStatusOk,
|
||||
TailnetStatusLost:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AllTailnetStatusValues() []TailnetStatus {
|
||||
return []TailnetStatus{
|
||||
TailnetStatusOk,
|
||||
TailnetStatusLost,
|
||||
}
|
||||
}
|
||||
|
||||
// Defines the user status: active, dormant, or suspended.
|
||||
type UserStatus string
|
||||
|
||||
@ -1865,6 +1923,21 @@ type TailnetCoordinator struct {
|
||||
HeartbeatAt time.Time `db:"heartbeat_at" json:"heartbeat_at"`
|
||||
}
|
||||
|
||||
type TailnetPeer struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Node []byte `db:"node" json:"node"`
|
||||
Status TailnetStatus `db:"status" json:"status"`
|
||||
}
|
||||
|
||||
type TailnetTunnel struct {
|
||||
CoordinatorID uuid.UUID `db:"coordinator_id" json:"coordinator_id"`
|
||||
SrcID uuid.UUID `db:"src_id" json:"src_id"`
|
||||
DstID uuid.UUID `db:"dst_id" json:"dst_id"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
}
|
||||
|
||||
// Joins in the username + avatar url of the created by user.
|
||||
type Template struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
|
@ -36,6 +36,8 @@ const (
|
||||
UniqueTailnetClientSubscriptionsPkey UniqueConstraint = "tailnet_client_subscriptions_pkey" // ALTER TABLE ONLY tailnet_client_subscriptions ADD CONSTRAINT tailnet_client_subscriptions_pkey PRIMARY KEY (client_id, coordinator_id, agent_id);
|
||||
UniqueTailnetClientsPkey UniqueConstraint = "tailnet_clients_pkey" // ALTER TABLE ONLY tailnet_clients ADD CONSTRAINT tailnet_clients_pkey PRIMARY KEY (id, coordinator_id);
|
||||
UniqueTailnetCoordinatorsPkey UniqueConstraint = "tailnet_coordinators_pkey" // ALTER TABLE ONLY tailnet_coordinators ADD CONSTRAINT tailnet_coordinators_pkey PRIMARY KEY (id);
|
||||
UniqueTailnetPeersPkey UniqueConstraint = "tailnet_peers_pkey" // ALTER TABLE ONLY tailnet_peers ADD CONSTRAINT tailnet_peers_pkey PRIMARY KEY (id, coordinator_id);
|
||||
UniqueTailnetTunnelsPkey UniqueConstraint = "tailnet_tunnels_pkey" // ALTER TABLE ONLY tailnet_tunnels ADD CONSTRAINT tailnet_tunnels_pkey PRIMARY KEY (coordinator_id, src_id, dst_id);
|
||||
UniqueTemplateVersionParametersTemplateVersionIDNameKey UniqueConstraint = "template_version_parameters_template_version_id_name_key" // ALTER TABLE ONLY template_version_parameters ADD CONSTRAINT template_version_parameters_template_version_id_name_key UNIQUE (template_version_id, name);
|
||||
UniqueTemplateVersionVariablesTemplateVersionIDNameKey UniqueConstraint = "template_version_variables_template_version_id_name_key" // ALTER TABLE ONLY template_version_variables ADD CONSTRAINT template_version_variables_template_version_id_name_key UNIQUE (template_version_id, name);
|
||||
UniqueTemplateVersionsPkey UniqueConstraint = "template_versions_pkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_pkey PRIMARY KEY (id);
|
||||
|
Reference in New Issue
Block a user