class Puppetfactory::Plugins::Gitea

Public Class Methods

new(options) click to toggle source
Calls superclass method Puppetfactory::Plugins::new
# File lib/puppetfactory/plugins/gitea.rb, line 8
def initialize(options)
  super(options)

  @cache_dir      = '/var/cache/puppetfactory/gitea'
  @lockfile       = '/var/cache/puppetfactory/gitea.lock'
  @templatedir    = options[:templatedir]
  @suffix         = options[:usersuffix]
  @controlrepo    = options[:controlrepo]
  @reponame       = File.basename(@controlrepo, '.git')
  @repopath       = "#{@cache_dir}/#{@reponame}"
  @gitea_upstream = options[:gitea_upstream]       || "https://github.com/puppetlabs-education/#{@controlrepo}"
  @gitea_cmd      = options[:gitea_cmd]            || '/home/git/go/bin/gitea'
  @admin_username = options[:gitea_admin_username] || 'root'
  @admin_password = options[:gitea_admin_password] || 'puppetlabs'
  @gitea_port     = options[:gitea_port]           || '3000'
  @gitea_user     = options[:gitea_user]           || 'git'
  @gitea_homedir  = Dir.home(@gitea_user)

  # the rest of this method is for the big boys only
  return unless Process.euid == 0

  # gitea will scream if the admin's .ssh directory doesn't exist
  FileUtils.mkdir_p(File.expand_path("~#{@admin_username}/.ssh"))

  migrate_repo! unless File.directory?(@repopath)
end

Public Instance Methods

create(username, password) click to toggle source
# File lib/puppetfactory/plugins/gitea.rb, line 35
def create(username, password)
  begin
    # since we're changing directories, none of this can be done concurrently; lock it all.
    #
    # TODO: consider forking worker processes so that CWD doesn't leak between threads.
    File.open(@lockfile, 'w') do |file|
      file.flock(File::LOCK_EX)

      make_user(username, password)
      $logger.debug "Created Gitea user #{username}."
      make_branch(username)
      $logger.debug "Created Gitea branch #{username}."
      add_collaborator(@admin_username, @reponame, username, 'write')
      $logger.info "Created Gitea collaborator #{username}."
    end
  rescue => e
    $logger.error "Error configuring Gitea for #{username}: #{e.message}"
    $logger.error e.backtrace.join("\n")
    return false
  end

  true
end
delete(username) click to toggle source
# File lib/puppetfactory/plugins/gitea.rb, line 59
def delete(username)
  begin
    remove_user(username)
    $logger.info "Removed Gitea user #{username}."
  rescue => e
    $logger.error "Error removing Gitea user #{username}: #{e.message}"
    return false
  end

  true
end

Private Instance Methods

add_collaborator(owner, repo, username, permission) click to toggle source
# File lib/puppetfactory/plugins/gitea.rb, line 126
def add_collaborator(owner, repo, username, permission)
  repo_uri = "http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/api/v1/repos/#{owner}/#{repo}/collaborators/#{username}"
  RestClient.put(repo_uri, {'permissions' => permission}.to_json)
end
make_branch(username) click to toggle source
# File lib/puppetfactory/plugins/gitea.rb, line 131
def make_branch(username)
  Dir.chdir(@repopath) do
    # use --force in case the branch already exists
    output, status = Open3.capture2e('git', 'branch', '--force', username)
    raise output unless status.success?

    output, status = Open3.capture2e('git', 'push', 'origin', username)
    raise output unless status.success?
  end
end
make_user(username, password) click to toggle source
# File lib/puppetfactory/plugins/gitea.rb, line 104
def make_user(username, password)
  Dir.chdir(@gitea_homedir) do
    uid = Etc.getpwnam(@gitea_user).uid
    pid = Process.fork do
      ENV['USER']  = @gitea_user
      Process.uid  = uid
      Process.euid = uid

      output, status = Open3.capture2e(@gitea_cmd, 'admin', 'create-user',
                                        '--name',     username,
                                        '--password', password,
                                        '--email',    "#{username}@#{@suffix}")

      $logger.error output unless status.success?
      exit status.exitstatus
    end

    pid, status = Process.wait2(pid)
    raise "Error creating Gitea user #{username}" unless status.success?
  end
end
migrate_repo!() click to toggle source
# File lib/puppetfactory/plugins/gitea.rb, line 72
def migrate_repo!
  FileUtils::mkdir_p @cache_dir
  $logger.info "Migrating repository #{@reponame}"
  begin
    RestClient.post("http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/api/v1/repos/migrate", {
                      'clone_addr' => @gitea_upstream,
                      'uid'        => 1,
                      'repo_name'  => @reponame,
                   })

    # make sure the server has time to finish cloning from GitHub before cloning
    sleep 5

    Dir.chdir(@cache_dir) do
      repo_uri = "http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/#{@admin_username}/#{@controlrepo}"
      output, status = Open3.capture2e('git', 'clone', '--depth', '1', repo_uri)
      raise output unless status.success?
    end

    hookfile = File.expand_path("~#{@gitea_user}/gitea-repositories/root/#{@controlrepo}/hooks/pre-receive.d/pre-receive")
    File.open(hookfile, 'w') do |f|
      f.write ERB.new(File.read("#{@templatedir}/pre-receive.erb")).result(binding)
    end
    FileUtils.chmod 0755, hookfile

  rescue => e
    $logger.error "Error migrating repository: #{e.message}"
    $logger.error e.backtrace.join("\n")
    return false
  end
end
remove_user(username) click to toggle source
# File lib/puppetfactory/plugins/gitea.rb, line 142
def remove_user(username)
  RestClient.delete("http://#{@admin_username}:#{@admin_password}@localhost:#{@gitea_port}/api/v1/admin/users/#{username}")
end