File: server_setup.rb

package info (click to toggle)
ruby-mongo 2.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,020 kB
  • sloc: ruby: 110,810; makefile: 5
file content (106 lines) | stat: -rw-r--r-- 2,841 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
require 'mongo'
require_relative '../../spec/support/utils'
require_relative '../../spec/support/spec_setup'

Mongo::Logger.logger.level = :WARN

class ServerSetup
  def setup_aws_auth
    arn = env!('MONGO_RUBY_DRIVER_AWS_AUTH_USER_ARN')
    puts "Adding AWS-mapped user #{wildcard_arn(arn)} for #{arn}"
    create_aws_user(arn)

    puts 'Setup done'
  end

  def setup_tags
    cfg = client.command(replSetGetConfig: 1).documents.first.fetch('config')
    members = cfg['members'].sort_by { |info| info['host'] }
    members.each_with_index do |member, index|
      # For case-sensitive tag set testing, add a mixed case tag.
      unless member['arbiterOnly']
        member['tags']['nodeIndex'] = index.to_s
      end
    end
    cfg['members'] = members
    cfg['version'] = cfg['version'] + 1
    client.command(replSetReconfig: cfg)
  end

  def require_api_version
    client.cluster.next_primary
    # In sharded clusters, the parameter must be set on each mongos.
    if Mongo::Cluster::Topology::Sharded === client.cluster.topology
      client.cluster.servers.each do |server|
        host = server.address.seed
        Mongo::Client.new([host], client.options.merge(connect: :direct)) do |c|
          c.command(setParameter: 1, requireApiVersion: true)
        end
      end
    else
      client.command(setParameter: 1, requireApiVersion: true)
    end
  end

  private

  # Creates an appropriate AWS mapped user for the provided ARN.
  #
  # The mapped user does not use the specified ARN directly but instead
  # uses a derived wildcard ARN. Because of this, multiple ARNs can map
  # to the same user.
  def create_aws_user(arn)
    bootstrap_client.use('$external').database.users.create(
      wildcard_arn(arn),
      roles: [{role: 'root', db: 'admin'}],
      write_concern: {w: :majority, wtimeout: 5000},
    )
  end

  def wildcard_arn(arn)
    if arn.start_with?('arn:aws:sts::')
      arn.sub(%r,/[^/]+\z,, '/*')
    else
      arn
    end
  end

  def require_env_vars(vars)
    vars.each do |var|
      unless env?(var)
        raise "#{var} must be set in environment"
      end
    end
  end

  def env?(key)
    ENV[key] && !ENV[key].empty?
  end

  def env!(key)
    ENV[key].tap do |value|
      if value.nil? || value.empty?
        raise "Value for #{key} is required in environment"
      end
    end
  end

  def env_true?(key)
    %w(1 true yes).include?(ENV[key]&.downcase)
  end

  def client
    @client ||= Mongo::Client.new(
      SpecConfig.instance.addresses,
      SpecConfig.instance.all_test_options.merge(
        socket_timeout: 5, connect_timeout: 5
      )
    )
  end

  def bootstrap_client
    @bootstrap_client ||= Mongo::Client.new(ENV['MONGODB_URI'] || %w(localhost),
      user: 'bootstrap', password: 'bootstrap', auth_mech: :scram, auth_mech_properties: nil,
    )
  end
end