Commit fed8ebc8 authored by Nick Thomas's avatar Nick Thomas

Stop needing SSH keys for Geo primaries

parent 6e62aab2
export default class GeoNodeForm {
constructor(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.$primaryCheckbox = this.$container.find("input[type='checkbox']");
this.$primaryCheckbox.on('change', () => this.onPrimaryCheckboxChange());
......
class GeoNode < ActiveRecord::Base
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
has_many :geo_node_namespace_links
......@@ -22,6 +22,8 @@ class GeoNode < ActiveRecord::Base
validates :access_key, presence: true
validates :encrypted_secret_access_key, presence: true
validates :geo_node_key, presence: true, if: :secondary?
after_initialize :build_dependents
after_save :expire_cache!
after_destroy :expire_cache!
......@@ -172,13 +174,15 @@ class GeoNode < ActiveRecord::Base
end
def build_dependents
unless persisted?
self.build_geo_node_key unless geo_node_key.present?
end
build_geo_node_key if new_record? && secondary? && geo_node_key.nil?
end
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?
self.oauth_application = nil
......
class GeoNodeKey < Key
has_one :geo_node
has_one :geo_node, inverse_of: :geo_node_key
def orphaned?
self.geo_nodes.length == 0
......
......@@ -12,8 +12,9 @@
.col-sm-10
= 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-group
.form-group.js-hide-if-geo-primary{ class: ('hidden' unless geo_node.secondary?) }
= fg.label :key, 'Public Key', class: 'control-label'
.col-sm-10
= fg.text_area :key, class: 'form-control thin_area', rows: 5, disabled: disable_key_edit
......@@ -22,7 +23,7 @@
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')
.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'
.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' }
......
---
title: Geo primary nodes no longer require SSH keys
merge_request: 2861
author:
type: changed
......@@ -79,33 +79,21 @@ namespace :geo do
end
desc 'Make this node the Geo primary'
task :set_primary_node, [:ssh_key_filename] => :environment do |_, args|
filename = args[:ssh_key_filename]
task set_primary_node: :environment do
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?
public_key = load_ssh_public_key(filename)
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
set_primary_geo_node
end
def set_primary_geo_node(public_key)
params = { schema: Gitlab.config.gitlab.protocol,
host: Gitlab.config.gitlab.host,
port: Gitlab.config.gitlab.port,
relative_url_root: Gitlab.config.gitlab.relative_url_root,
primary: true,
geo_node_key_attributes: { key: public_key } }
def set_primary_geo_node
params = {
schema: Gitlab.config.gitlab.protocol,
host: Gitlab.config.gitlab.host,
port: Gitlab.config.gitlab.port,
relative_url_root: Gitlab.config.gitlab.relative_url_root,
primary: true
}
node = GeoNode.new(params)
puts "Saving primary GeoNode with URL #{node.url}".color(:green)
......
......@@ -7,6 +7,7 @@ FactoryGirl.define do
trait :primary do
primary true
port { Gitlab.config.gitlab.port }
geo_node_key nil
end
trait :current do
......
require 'spec_helper'
describe GeoNode, type: :model do
subject(:new_node) { create(:geo_node, schema: 'https', host: 'localhost', port: 3000, relative_url_root: 'gitlab', primary: false) }
subject(:new_primary_node) { create(:geo_node, schema: 'https', host: 'localhost', port: 3000, relative_url_root: 'gitlab', primary: true) }
subject(:empty_node) { described_class.new }
subject(:primary_node) { create(:geo_node, :primary) }
subject(:node) { create(:geo_node) }
let(:new_node) { create(:geo_node, schema: 'https', host: 'localhost', port: 3000, relative_url_root: 'gitlab') }
let(:new_primary_node) { create(:geo_node, :primary, schema: 'https', host: 'localhost', port: 3000, relative_url_root: 'gitlab') }
let(:empty_node) { described_class.new }
let(:primary_node) { create(:geo_node, :primary) }
let(:node) { create(:geo_node) }
let(:dummy_url) { 'https://localhost:3000/gitlab' }
let(:url_helpers) { Gitlab::Routing.url_helpers }
......@@ -19,9 +19,12 @@ describe GeoNode, type: :model do
it { is_expected.to have_many(:namespaces).through(:geo_node_namespace_links) }
end
context 'default values' do
subject { described_class.new }
context 'validations' do
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' }
before do
......@@ -29,23 +32,23 @@ describe GeoNode, type: :model do
end
it 'defines a default schema' do
expect(subject.schema).to eq('http')
expect(empty_node.schema).to eq('http')
end
it 'defines a default host' do
expect(subject.host).to eq(gitlab_host)
expect(empty_node.host).to eq(gitlab_host)
end
it 'defines a default port' do
expect(subject.port).to eq(80)
expect(empty_node.port).to eq(80)
end
it 'defines a default relative_url_root' do
expect(subject.relative_url_root).to eq('')
expect(empty_node.relative_url_root).to eq('')
end
it 'defines a default primary flag' do
expect(subject.primary).to eq(false)
expect(empty_node.primary).to eq(false)
end
end
......@@ -100,7 +103,7 @@ describe GeoNode, type: :model do
let(:new_node) { FactoryGirl.build(:geo_node) }
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!
end
......@@ -315,4 +318,34 @@ describe GeoNode, type: :model do
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
......@@ -6,32 +6,23 @@ describe 'geo rake tasks' do
end
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
expect(Gitlab::Geo).to receive(:license_allows?).and_return(true)
stub_config_setting(protocol: 'https')
end
it 'creates a GeoNode' do
begin
file = Tempfile.new('geo-test-')
file.write(ssh_key)
path = file.path
file.close
expect(GeoNode.count).to eq(0)
run_rake_task('geo:set_primary_node')
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)
node = GeoNode.first
expect(node.schema).to eq('https')
expect(node.primary).to be_truthy
expect(node.geo_node_key.key).to eq(ssh_key)
ensure
file.unlink
end
expect(node.schema).to eq('https')
expect(node.primary).to be_truthy
expect(node.geo_node_key).to be_nil
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