Commit 2f61a0b5 authored by Thong Kuah's avatar Thong Kuah

Add models and tables

- cluster_agent
- cluster_agent_tokens

Adds encrypted token using TokenAuthenticatable module

Add has_many :cluster_agents

Add to spec all_models.yml checklist. cluster_agents should not be
exported as part of project export, so not putting in import_export.yml.
parent c00c10ed
# frozen_string_literal: true
module Clusters
class Agent < ApplicationRecord
self.table_name = 'cluster_agents'
belongs_to :project, class_name: '::Project' # Otherwise, it will load ::Clusters::Project
has_many :agent_tokens, class_name: 'Clusters::AgentToken'
validates :name, presence: true, length: { maximum: 255 }, uniqueness: { scope: :project_id }
end
end
# frozen_string_literal: true
module Clusters
class AgentToken < ApplicationRecord
include TokenAuthenticatable
add_authentication_token_field :token, encrypted: :required
self.table_name = 'cluster_agent_tokens'
belongs_to :agent, class_name: 'Clusters::Agent'
before_save :ensure_token
end
end
...@@ -261,6 +261,7 @@ class Project < ApplicationRecord ...@@ -261,6 +261,7 @@ class Project < ApplicationRecord
has_many :clusters, through: :cluster_project, class_name: 'Clusters::Cluster' has_many :clusters, through: :cluster_project, class_name: 'Clusters::Cluster'
has_many :kubernetes_namespaces, class_name: 'Clusters::KubernetesNamespace' has_many :kubernetes_namespaces, class_name: 'Clusters::KubernetesNamespace'
has_many :management_clusters, class_name: 'Clusters::Cluster', foreign_key: :management_project_id, inverse_of: :management_project has_many :management_clusters, class_name: 'Clusters::Cluster', foreign_key: :management_project_id, inverse_of: :management_project
has_many :cluster_agents, class_name: 'Clusters::Agent'
has_many :prometheus_metrics has_many :prometheus_metrics
has_many :prometheus_alerts, inverse_of: :project has_many :prometheus_alerts, inverse_of: :project
......
---
title: Adds models and tables for cluster agent and cluster agent tokens
merge_request: 33228
author:
type: other
# frozen_string_literal: true
class CreateClusterAgents < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless table_exists?(:cluster_agents)
with_lock_retries do
create_table :cluster_agents do |t|
t.timestamps_with_timezone null: false
t.belongs_to(:project, null: false, index: true, foreign_key: { on_delete: :cascade })
t.text :name, null: false
t.index [:project_id, :name], unique: true
end
end
end
add_text_limit :cluster_agents, :name, 255
end
def down
with_lock_retries do
drop_table :cluster_agents
end
end
end
# frozen_string_literal: true
class CreateClusterAgentTokens < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless table_exists?(:cluster_agent_tokens)
create_table :cluster_agent_tokens do |t|
t.timestamps_with_timezone null: false
t.belongs_to :agent, null: false, index: true, foreign_key: { to_table: :cluster_agents, on_delete: :cascade }
t.text :token_encrypted, null: false
t.index :token_encrypted, unique: true
end
end
add_text_limit :cluster_agent_tokens, :token_encrypted, 255
end
def down
drop_table :cluster_agent_tokens
end
end
...@@ -10374,6 +10374,42 @@ CREATE SEQUENCE public.ci_variables_id_seq ...@@ -10374,6 +10374,42 @@ CREATE SEQUENCE public.ci_variables_id_seq
ALTER SEQUENCE public.ci_variables_id_seq OWNED BY public.ci_variables.id; ALTER SEQUENCE public.ci_variables_id_seq OWNED BY public.ci_variables.id;
CREATE TABLE public.cluster_agent_tokens (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
agent_id bigint NOT NULL,
token_encrypted text NOT NULL,
CONSTRAINT check_c60daed227 CHECK ((char_length(token_encrypted) <= 255))
);
CREATE SEQUENCE public.cluster_agent_tokens_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE public.cluster_agent_tokens_id_seq OWNED BY public.cluster_agent_tokens.id;
CREATE TABLE public.cluster_agents (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
project_id bigint NOT NULL,
name text NOT NULL,
CONSTRAINT check_3498369510 CHECK ((char_length(name) <= 255))
);
CREATE SEQUENCE public.cluster_agents_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE public.cluster_agents_id_seq OWNED BY public.cluster_agents.id;
CREATE TABLE public.cluster_groups ( CREATE TABLE public.cluster_groups (
id integer NOT NULL, id integer NOT NULL,
cluster_id integer NOT NULL, cluster_id integer NOT NULL,
...@@ -16572,6 +16608,10 @@ ALTER TABLE ONLY public.ci_triggers ALTER COLUMN id SET DEFAULT nextval('public. ...@@ -16572,6 +16608,10 @@ ALTER TABLE ONLY public.ci_triggers ALTER COLUMN id SET DEFAULT nextval('public.
ALTER TABLE ONLY public.ci_variables ALTER COLUMN id SET DEFAULT nextval('public.ci_variables_id_seq'::regclass); ALTER TABLE ONLY public.ci_variables ALTER COLUMN id SET DEFAULT nextval('public.ci_variables_id_seq'::regclass);
ALTER TABLE ONLY public.cluster_agent_tokens ALTER COLUMN id SET DEFAULT nextval('public.cluster_agent_tokens_id_seq'::regclass);
ALTER TABLE ONLY public.cluster_agents ALTER COLUMN id SET DEFAULT nextval('public.cluster_agents_id_seq'::regclass);
ALTER TABLE ONLY public.cluster_groups ALTER COLUMN id SET DEFAULT nextval('public.cluster_groups_id_seq'::regclass); ALTER TABLE ONLY public.cluster_groups ALTER COLUMN id SET DEFAULT nextval('public.cluster_groups_id_seq'::regclass);
ALTER TABLE ONLY public.cluster_platforms_kubernetes ALTER COLUMN id SET DEFAULT nextval('public.cluster_platforms_kubernetes_id_seq'::regclass); ALTER TABLE ONLY public.cluster_platforms_kubernetes ALTER COLUMN id SET DEFAULT nextval('public.cluster_platforms_kubernetes_id_seq'::regclass);
...@@ -17519,6 +17559,12 @@ ALTER TABLE ONLY public.ci_triggers ...@@ -17519,6 +17559,12 @@ ALTER TABLE ONLY public.ci_triggers
ALTER TABLE ONLY public.ci_variables ALTER TABLE ONLY public.ci_variables
ADD CONSTRAINT ci_variables_pkey PRIMARY KEY (id); ADD CONSTRAINT ci_variables_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.cluster_agent_tokens
ADD CONSTRAINT cluster_agent_tokens_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.cluster_agents
ADD CONSTRAINT cluster_agents_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.cluster_groups ALTER TABLE ONLY public.cluster_groups
ADD CONSTRAINT cluster_groups_pkey PRIMARY KEY (id); ADD CONSTRAINT cluster_groups_pkey PRIMARY KEY (id);
...@@ -19021,6 +19067,14 @@ CREATE INDEX index_ci_triggers_on_project_id ON public.ci_triggers USING btree ( ...@@ -19021,6 +19067,14 @@ CREATE INDEX index_ci_triggers_on_project_id ON public.ci_triggers USING btree (
CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_scope ON public.ci_variables USING btree (project_id, key, environment_scope); CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_scope ON public.ci_variables USING btree (project_id, key, environment_scope);
CREATE INDEX index_cluster_agent_tokens_on_agent_id ON public.cluster_agent_tokens USING btree (agent_id);
CREATE UNIQUE INDEX index_cluster_agent_tokens_on_token_encrypted ON public.cluster_agent_tokens USING btree (token_encrypted);
CREATE INDEX index_cluster_agents_on_project_id ON public.cluster_agents USING btree (project_id);
CREATE UNIQUE INDEX index_cluster_agents_on_project_id_and_name ON public.cluster_agents USING btree (project_id, name);
CREATE UNIQUE INDEX index_cluster_groups_on_cluster_id_and_group_id ON public.cluster_groups USING btree (cluster_id, group_id); CREATE UNIQUE INDEX index_cluster_groups_on_cluster_id_and_group_id ON public.cluster_groups USING btree (cluster_id, group_id);
CREATE INDEX index_cluster_groups_on_group_id ON public.cluster_groups USING btree (group_id); CREATE INDEX index_cluster_groups_on_group_id ON public.cluster_groups USING btree (group_id);
...@@ -21712,6 +21766,9 @@ ALTER TABLE ONLY public.group_custom_attributes ...@@ -21712,6 +21766,9 @@ ALTER TABLE ONLY public.group_custom_attributes
ALTER TABLE ONLY public.requirements_management_test_reports ALTER TABLE ONLY public.requirements_management_test_reports
ADD CONSTRAINT fk_rails_24cecc1e68 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL; ADD CONSTRAINT fk_rails_24cecc1e68 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
ALTER TABLE ONLY public.cluster_agents
ADD CONSTRAINT fk_rails_25e9fc2d5d FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.group_wiki_repositories ALTER TABLE ONLY public.group_wiki_repositories
ADD CONSTRAINT fk_rails_26f867598c FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE; ADD CONSTRAINT fk_rails_26f867598c FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
...@@ -22510,6 +22567,9 @@ ALTER TABLE ONLY public.subscriptions ...@@ -22510,6 +22567,9 @@ ALTER TABLE ONLY public.subscriptions
ALTER TABLE ONLY public.operations_strategies ALTER TABLE ONLY public.operations_strategies
ADD CONSTRAINT fk_rails_d183b6e6dd FOREIGN KEY (feature_flag_id) REFERENCES public.operations_feature_flags(id) ON DELETE CASCADE; ADD CONSTRAINT fk_rails_d183b6e6dd FOREIGN KEY (feature_flag_id) REFERENCES public.operations_feature_flags(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.cluster_agent_tokens
ADD CONSTRAINT fk_rails_d1d26abc25 FOREIGN KEY (agent_id) REFERENCES public.cluster_agents(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.requirements_management_test_reports ALTER TABLE ONLY public.requirements_management_test_reports
ADD CONSTRAINT fk_rails_d1e8b498bf FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL; ADD CONSTRAINT fk_rails_d1e8b498bf FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
...@@ -23756,6 +23816,8 @@ COPY "schema_migrations" (version) FROM STDIN; ...@@ -23756,6 +23816,8 @@ COPY "schema_migrations" (version) FROM STDIN;
20200605160806 20200605160806
20200605160836 20200605160836
20200605160851 20200605160851
20200607223047
20200607235435
20200608072931 20200608072931
20200608075553 20200608075553
20200608195222 20200608195222
......
# frozen_string_literal: true
FactoryBot.define do
factory :cluster_agent_token, class: 'Clusters::AgentToken' do
association :agent, factory: :cluster_agent
token_encrypted { Gitlab::CryptoHelper.aes256_gcm_encrypt(SecureRandom.hex(50)) }
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :cluster_agent, class: 'Clusters::Agent' do
project
sequence(:name) { |n| "agent_#{n}" }
end
end
...@@ -312,6 +312,7 @@ project: ...@@ -312,6 +312,7 @@ project:
- chat_services - chat_services
- cluster - cluster
- clusters - clusters
- cluster_agents
- cluster_project - cluster_project
- creator - creator
- cycle_analytics_stages - cycle_analytics_stages
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Clusters::Agent do
subject { create(:cluster_agent) }
it { is_expected.to belong_to(:project).class_name('::Project') }
it { is_expected.to have_many(:agent_tokens).class_name('Clusters::AgentToken') }
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_length_of(:name).is_at_most(255) }
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Clusters::AgentToken do
it { is_expected.to belong_to(:agent).class_name('Clusters::Agent') }
describe '#token' do
it 'is generated on save' do
agent_token = build(:cluster_agent_token, token_encrypted: nil)
expect(agent_token.token).to be_nil
agent_token.save!
expect(agent_token.token).to be_present
end
end
end
...@@ -104,6 +104,7 @@ RSpec.describe Project do ...@@ -104,6 +104,7 @@ RSpec.describe Project do
it { is_expected.to have_many(:clusters) } it { is_expected.to have_many(:clusters) }
it { is_expected.to have_many(:management_clusters).class_name('Clusters::Cluster') } it { is_expected.to have_many(:management_clusters).class_name('Clusters::Cluster') }
it { is_expected.to have_many(:kubernetes_namespaces) } it { is_expected.to have_many(:kubernetes_namespaces) }
it { is_expected.to have_many(:cluster_agents).class_name('Clusters::Agent') }
it { is_expected.to have_many(:custom_attributes).class_name('ProjectCustomAttribute') } it { is_expected.to have_many(:custom_attributes).class_name('ProjectCustomAttribute') }
it { is_expected.to have_many(:project_badges).class_name('ProjectBadge') } it { is_expected.to have_many(:project_badges).class_name('ProjectBadge') }
it { is_expected.to have_many(:lfs_file_locks) } it { is_expected.to have_many(:lfs_file_locks) }
......
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