summaryrefslogtreecommitdiff
path: root/lib/license/management/tool_box.rb
blob: d2fe7032a42129bd07f1a3d31e108411c9ce7cd5 (plain)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# frozen_string_literal: true

module License
  module Management
    class ToolBox
      attr_reader :project_path, :shell

      def initialize(shell, project_path)
        @shell = shell
        @project_path = project_path
      end

      def install(tool:, version: version_of(tool), env: {})
        Dir.chdir(project_path) do
          deb = deb_for(tool, version)
          if deb&.exist?
            shell.execute([:dpkg, '-i', deb])
          elsif tool == :nodejs
            shell.execute(['/opt/asdf/plugins/nodejs/bin/import-release-team-keyring'])
          end
          shell.execute([:asdf, :install, tool.to_s, version], env: env)
          shell.execute([:asdf, :local, tool.to_s, version], env: env)
          shell.execute([:asdf, :reshim], env: env)
        end

        install_certificates_into_java_keystore(env) if tool == :java
      end

      def version_of(tool, env: ENV)
        Dir.chdir(project_path) do
          case tool
          when :java
            java_version(env: env)
          when :python
            python_version(env: env)
          else
            asdf_detected_version_of(tool)
          end
        end
      end

      def default_version_for(tool)
        default_versions[tool.to_sym]
      end

      def uninstall(tool:, version:)
        Dir.chdir(project_path) do
          return unless deb_for(tool, version)&.exist?

          shell.execute([:dpkg, '-r', "#{tool}-#{version}"])
          shell.execute([:asdf, :reshim])
        end
      end

      def closest_match_to(tool:, version:)
        deb = deb_for(tool, version)
        deb.basename.to_s.gsub("#{tool}-", "").split('_', 2)[0] if deb&.exist?
      end

      private

      def deb_for(tool, version)
        Pathname.glob("/opt/toolcache/#{tool}-#{version}*.deb")[0]
      end

      def version_error_for(tool)
        /\Aversion\s(?<version>.+)\sis not installed for #{tool}\z/
      end

      def default_versions
        @default_versions ||=
          IO.read('/opt/gitlab/.tool-versions').each_line.each_with_object({}) do |line, memo|
            name, version = line.chomp.split(' ', 2)
            memo[name.to_sym] = version
          end
      end

      def asdf_detected_version_of(tool)
        stdout, stderr, status = shell.execute([:asdf, :current, tool.to_s])

        if status.success?
          version, _ = stdout.split(' ', 2)
          version
        else
          match = stderr.chomp.match(version_error_for(tool))
          match ? match[:version] : default_version_for(tool)
        end
      end

      def python_version(env:)
        case env['LM_PYTHON_VERSION']
        when '3'
          default_version_for(:python)
        when '2'
          closest_match_to(tool: :python, version: "2.")
        else
          major, minor, _rest = (env['ASDF_PYTHON_VERSION'] || asdf_detected_version_of(:python)).split('.')
          closest_match_to(tool: :python, version: "#{major}.#{minor}")
        end
      end

      def java_version(env:)
        lm_version = env['LM_JAVA_VERSION']
        return lm_version if lm_version && %w[8 11].include?(lm_version)

        asdf_version = env['ASDF_JAVA_VERSION']
        return asdf_version.gsub('adopt-openjdk', 'adoptopenjdk') if asdf_version

        asdf_detected_version_of(:java)
      end

      def install_certificates_into_java_keystore(env)
        Dir.chdir shell.custom_certificate_path.dirname do
          Dir.glob('custom.*.crt').each do |path|
            keystore_path = "#{env['JAVA_HOME']}/jre/lib/security/cacerts"
            shell.execute([:keytool, '-importcert', '-alias', Time.now.to_i, '-file', File.expand_path(path), '-trustcacerts', '-noprompt', '-storepass', 'changeit', '-keystore', keystore_path], env: env)
            shell.execute([:keytool, '-list', '-v', '-storepass changeit', '-keystore', keystore_path], env: env)
          end
        end
      end
    end
  end
end