Commit fed8ebc8 authored by Nick Thomas's avatar Nick Thomas

Stop needing SSH keys for Geo primaries

parent 6e62aab2
export default class GeoNodeForm { export default class GeoNodeForm {
constructor(container) { constructor(container) {
this.$container = container; this.$container = container;
this.$namespaces = this.$container.find('.js-namespaces'); this.$namespaces = this.$container.find('.js-hide-if-geo-primary');
this.$namespacesSelect = this.$namespaces.find('.select2'); this.$namespacesSelect = this.$namespaces.find('.select2');
this.$primaryCheckbox = this.$container.find("input[type='checkbox']"); this.$primaryCheckbox = this.$container.find("input[type='checkbox']");
this.$primaryCheckbox.on('change', () => this.onPrimaryCheckboxChange()); this.$primaryCheckbox.on('change', () => this.onPrimaryCheckboxChange());
......
class GeoNode < ActiveRecord::Base class GeoNode < ActiveRecord::Base
include Presentable include Presentable
belongs_to :geo_node_key, dependent: :destroy # rubocop: disable Cop/ActiveRecordDependent belongs_to :geo_node_key, inverse_of: :geo_node, dependent: :destroy # rubocop: disable Cop/ActiveRecordDependent
belongs_to :oauth_application, class_name: 'Doorkeeper::Application', dependent: :destroy # rubocop: disable Cop/ActiveRecordDependent belongs_to :oauth_application, class_name: 'Doorkeeper::Application', dependent: :destroy # rubocop: disable Cop/ActiveRecordDependent
has_many :geo_node_namespace_links has_many :geo_node_namespace_links
...@@ -22,6 +22,8 @@ class GeoNode < ActiveRecord::Base ...@@ -22,6 +22,8 @@ class GeoNode < ActiveRecord::Base
validates :access_key, presence: true validates :access_key, presence: true
validates :encrypted_secret_access_key, presence: true validates :encrypted_secret_access_key, presence: true
validates :geo_node_key, presence: true, if: :secondary?
after_initialize :build_dependents after_initialize :build_dependents
after_save :expire_cache! after_save :expire_cache!
after_destroy :expire_cache! after_destroy :expire_cache!
...@@ -172,13 +174,15 @@ class GeoNode < ActiveRecord::Base ...@@ -172,13 +174,15 @@ class GeoNode < ActiveRecord::Base
end end
def build_dependents def build_dependents
unless persisted? build_geo_node_key if new_record? && secondary? && geo_node_key.nil?
self.build_geo_node_key unless geo_node_key.present?
end
end end
def update_dependents_attributes def update_dependents_attributes
self.geo_node_key&.title = "Geo node: #{self.url}" if primary?
self.geo_node_key = nil
else
self.geo_node_key&.title = "Geo node: #{self.url}"
end
if self.primary? if self.primary?
self.oauth_application = nil self.oauth_application = nil
......
class GeoNodeKey < Key class GeoNodeKey < Key
has_one :geo_node has_one :geo_node, inverse_of: :geo_node_key
def orphaned? def orphaned?
self.geo_nodes.length == 0 self.geo_nodes.length == 0
......
...@@ -12,8 +12,9 @@ ...@@ -12,8 +12,9 @@
.col-sm-10 .col-sm-10
= form.text_field :url, class: 'form-control' = form.text_field :url, class: 'form-control'
= form.fields_for :geo_node_key, geo_node.geo_node_key, include_id: !disable_key_edit do |fg| = form.fields_for :geo_node_key, geo_node.geo_node_key, include_id: !disable_key_edit do |fg|
.form-group .form-group.js-hide-if-geo-primary{ class: ('hidden' unless geo_node.secondary?) }
= fg.label :key, 'Public Key', class: 'control-label' = fg.label :key, 'Public Key', class: 'control-label'
.col-sm-10 .col-sm-10
= fg.text_area :key, class: 'form-control thin_area', rows: 5, disabled: disable_key_edit = fg.text_area :key, class: 'form-control thin_area', rows: 5, disabled: disable_key_edit
...@@ -22,7 +23,7 @@ ...@@ -22,7 +23,7 @@
Paste the ssh public key used by the node you are adding. Read more about it Paste the ssh public key used by the node you are adding. Read more about it
= link_to 'here', help_page_path('gitlab-geo/configuration.html', anchor: 'step-5-enabling-the-secondary-gitlab-node') = link_to 'here', help_page_path('gitlab-geo/configuration.html', anchor: 'step-5-enabling-the-secondary-gitlab-node')
.form-group.js-namespaces{ class: ('hidden' unless geo_node.new_record? || geo_node.secondary?) } .form-group.js-hide-if-geo-primary{ class: ('hidden' unless geo_node.secondary?) }
= form.label :namespace_ids, 'Namespaces to replicate', class: 'control-label' = form.label :namespace_ids, 'Namespaces to replicate', class: 'control-label'
.col-sm-10 .col-sm-10
= form.select :namespace_ids, namespaces_options(geo_node.namespace_ids), { include_hidden: true }, multiple: true, class: 'select2 select-wide', data: { field: 'namespace_ids' } = form.select :namespace_ids, namespaces_options(geo_node.namespace_ids), { include_hidden: true }, multiple: true, class: 'select2 select-wide', data: { field: 'namespace_ids' }
......
---
title: Geo primary nodes no longer require SSH keys
merge_request: 2861
author:
type: changed
...@@ -79,33 +79,21 @@ namespace :geo do ...@@ -79,33 +79,21 @@ namespace :geo do
end end
desc 'Make this node the Geo primary' desc 'Make this node the Geo primary'
task :set_primary_node, [:ssh_key_filename] => :environment do |_, args| task set_primary_node: :environment do
filename = args[:ssh_key_filename]
abort 'GitLab Geo is not supported with this license. Please contact sales@gitlab.com.' unless Gitlab::Geo.license_allows? abort 'GitLab Geo is not supported with this license. Please contact sales@gitlab.com.' unless Gitlab::Geo.license_allows?
abort 'You must specify a filename of an SSH public key' unless filename.present?
abort 'GitLab Geo primary node already present' if Gitlab::Geo.primary_node.present? abort 'GitLab Geo primary node already present' if Gitlab::Geo.primary_node.present?
public_key = load_ssh_public_key(filename) set_primary_geo_node
abort "Invalid SSH public key in #{filename}, aborting" unless public_key
set_primary_geo_node(public_key)
end
def load_ssh_public_key(filename)
File.open(filename).read
rescue => e
puts "Error opening #{filename}: #{e}".color(:red)
nil
end end
def set_primary_geo_node(public_key) def set_primary_geo_node
params = { schema: Gitlab.config.gitlab.protocol, params = {
host: Gitlab.config.gitlab.host, schema: Gitlab.config.gitlab.protocol,
port: Gitlab.config.gitlab.port, host: Gitlab.config.gitlab.host,
relative_url_root: Gitlab.config.gitlab.relative_url_root, port: Gitlab.config.gitlab.port,
primary: true, relative_url_root: Gitlab.config.gitlab.relative_url_root,
geo_node_key_attributes: { key: public_key } } primary: true
}
node = GeoNode.new(params) node = GeoNode.new(params)
puts "Saving primary GeoNode with URL #{node.url}".color(:green) puts "Saving primary GeoNode with URL #{node.url}".color(:green)
......
...@@ -7,6 +7,7 @@ FactoryGirl.define do ...@@ -7,6 +7,7 @@ FactoryGirl.define do
trait :primary do trait :primary do
primary true primary true
port { Gitlab.config.gitlab.port } port { Gitlab.config.gitlab.port }
geo_node_key nil
end end
trait :current do trait :current do
......
require 'spec_helper' require 'spec_helper'
describe GeoNode, type: :model do describe GeoNode, type: :model do
subject(:new_node) { create(:geo_node, schema: 'https', host: 'localhost', port: 3000, relative_url_root: 'gitlab', primary: false) } let(:new_node) { create(:geo_node, schema: 'https', host: 'localhost', port: 3000, relative_url_root: 'gitlab') }
subject(:new_primary_node) { create(:geo_node, schema: 'https', host: 'localhost', port: 3000, relative_url_root: 'gitlab', primary: true) } let(:new_primary_node) { create(:geo_node, :primary, schema: 'https', host: 'localhost', port: 3000, relative_url_root: 'gitlab') }
subject(:empty_node) { described_class.new } let(:empty_node) { described_class.new }
subject(:primary_node) { create(:geo_node, :primary) } let(:primary_node) { create(:geo_node, :primary) }
subject(:node) { create(:geo_node) } let(:node) { create(:geo_node) }
let(:dummy_url) { 'https://localhost:3000/gitlab' } let(:dummy_url) { 'https://localhost:3000/gitlab' }
let(:url_helpers) { Gitlab::Routing.url_helpers } let(:url_helpers) { Gitlab::Routing.url_helpers }
...@@ -19,9 +19,12 @@ describe GeoNode, type: :model do ...@@ -19,9 +19,12 @@ describe GeoNode, type: :model do
it { is_expected.to have_many(:namespaces).through(:geo_node_namespace_links) } it { is_expected.to have_many(:namespaces).through(:geo_node_namespace_links) }
end end
context 'default values' do context 'validations' do
subject { described_class.new } it { expect(new_node).to validate_presence_of(:geo_node_key) }
it { expect(new_primary_node).not_to validate_presence_of(:geo_node_key) }
end
context 'default values' do
let(:gitlab_host) { 'gitlabhost' } let(:gitlab_host) { 'gitlabhost' }
before do before do
...@@ -29,23 +32,23 @@ describe GeoNode, type: :model do ...@@ -29,23 +32,23 @@ describe GeoNode, type: :model do
end end
it 'defines a default schema' do it 'defines a default schema' do
expect(subject.schema).to eq('http') expect(empty_node.schema).to eq('http')
end end
it 'defines a default host' do it 'defines a default host' do
expect(subject.host).to eq(gitlab_host) expect(empty_node.host).to eq(gitlab_host)
end end
it 'defines a default port' do it 'defines a default port' do
expect(subject.port).to eq(80) expect(empty_node.port).to eq(80)
end end
it 'defines a default relative_url_root' do it 'defines a default relative_url_root' do
expect(subject.relative_url_root).to eq('') expect(empty_node.relative_url_root).to eq('')
end end
it 'defines a default primary flag' do it 'defines a default primary flag' do
expect(subject.primary).to eq(false) expect(empty_node.primary).to eq(false)
end end
end end
...@@ -100,7 +103,7 @@ describe GeoNode, type: :model do ...@@ -100,7 +103,7 @@ describe GeoNode, type: :model do
let(:new_node) { FactoryGirl.build(:geo_node) } let(:new_node) { FactoryGirl.build(:geo_node) }
it 'expires cache when saved' do it 'expires cache when saved' do
expect(new_node).to receive(:expire_cache!) expect(new_node).to receive(:expire_cache!).at_least(:once)
new_node.save! new_node.save!
end end
...@@ -315,4 +318,34 @@ describe GeoNode, type: :model do ...@@ -315,4 +318,34 @@ describe GeoNode, type: :model do
end end
end end
end end
describe '#geo_node_key' do
context 'primary node' do
it 'cannot be set' do
node = new_primary_node
expect(node.geo_node_key).to be_nil
node.geo_node_key = build(:geo_node_key)
expect(node).to be_valid
node.save!
expect(node.geo_node_key(true)).to be_nil
end
end
context 'secondary node' do
it 'is automatically set' do
node = build(:geo_node, url: 'http://example.com/')
expect(node.geo_node_key).to be_present
expect(node.geo_node_key.title).not_to include('example.com')
node.save!
expect(node.geo_node_key.title).to eq('Geo node: http://example.com/')
end
end
end
end end
...@@ -6,32 +6,23 @@ describe 'geo rake tasks' do ...@@ -6,32 +6,23 @@ describe 'geo rake tasks' do
end end
describe 'set_primary_node task' do describe 'set_primary_node task' do
let(:ssh_key) { 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUkxk8m9rVYZ1q4/5xpg3TwTM9QFw3TinPFkyWsiACFKjor3byV6g3vHWTuIS70E7wk2JTXGL0wdrfUG6iQDJuP0BYNxjkluB14nIAfPuXN7V73QY/cqvHogw5o6pPRFD+Szke6FzouNQ70Z/qrM1k7me3e9DMuscMMrMTOR2HLKppNQyP4Jp0WJOyncdWB2NxKXTezy/ZnHv+BdhC0q0JW3huIx9qkBCHio7x8BdyJLMF9KxNYIuCkbP3exs5wgb+qGrjSri6LfAVq8dJ2VYibWxdsUG6iITJF+G4qbcyQjgiMLbxCfNd9bjwmkxSGvFn2EPsAFKzxyAvYFWb/y91 test@host' }
before do before do
expect(Gitlab::Geo).to receive(:license_allows?).and_return(true) expect(Gitlab::Geo).to receive(:license_allows?).and_return(true)
stub_config_setting(protocol: 'https') stub_config_setting(protocol: 'https')
end end
it 'creates a GeoNode' do it 'creates a GeoNode' do
begin expect(GeoNode.count).to eq(0)
file = Tempfile.new('geo-test-')
file.write(ssh_key) run_rake_task('geo:set_primary_node')
path = file.path
file.close
expect(GeoNode.count).to eq(0) expect(GeoNode.count).to eq(1)
run_rake_task('geo:set_primary_node', path) node = GeoNode.first
expect(GeoNode.count).to eq(1) expect(node.schema).to eq('https')
node = GeoNode.first expect(node.primary).to be_truthy
expect(node.schema).to eq('https') expect(node.geo_node_key).to be_nil
expect(node.primary).to be_truthy
expect(node.geo_node_key.key).to eq(ssh_key)
ensure
file.unlink
end
end end
end end
end end
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