Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

define NetX class locally to remove external dependency #36

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .sync.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
---
Gemfile:
optional:
':test':
- gem: 'net_http_unix'
':test': []
.puppet-lint.rc:
enabled_lint_checks:
- parameter_documentation
Expand Down
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ group :test do
gem 'coveralls', :require => false
gem 'simplecov-console', :require => false
gem 'puppet_metadata', '~> 4.0', :require => false
gem 'net_http_unix', :require => false
end

group :development do
Expand Down
9 changes: 0 additions & 9 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ The following parameters are available in the `snap` class:
* [`service_enable`](#-snap--service_enable)
* [`core_snap_ensure`](#-snap--core_snap_ensure)
* [`manage_repo`](#-snap--manage_repo)
* [`net_http_unix_ensure`](#-snap--net_http_unix_ensure)

##### <a name="-snap--package_ensure"></a>`package_ensure`

Expand Down Expand Up @@ -69,14 +68,6 @@ Whether we should manage EPEL repo or not.

Default value: `false`

##### <a name="-snap--net_http_unix_ensure"></a>`net_http_unix_ensure`

Data type: `Enum['present', 'installed', 'absent']`

The state of net_http_unix gem.

Default value: `'installed'`

## Resource types

### <a name="snap_conf"></a>`snap_conf`
Expand Down
5 changes: 0 additions & 5 deletions lib/puppet/feature/net_http_unix_lib.rb

This file was deleted.

2 changes: 1 addition & 1 deletion lib/puppet/provider/package/snap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

commands snap_cmd: '/usr/bin/snap'
has_feature :installable, :versionable, :install_options, :uninstallable, :purgeable, :upgradeable
confine feature: %i[net_http_unix_lib snapd_socket]
confine feature: %i[snapd_socket]

mk_resource_methods

Expand Down
2 changes: 1 addition & 1 deletion lib/puppet/provider/snap_conf/snap_conf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Puppet::Type.type(:snap_conf).provide(:snap_conf) do
desc 'Manage snap configuration both system wide and snap specific.'

confine feature: %i[net_http_unix_lib snapd_socket]
confine feature: %i[snapd_socket]

def create
save_conf
Expand Down
47 changes: 45 additions & 2 deletions lib/puppet_x/snap/api.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,54 @@
# frozen_string_literal: true

require 'net_http_unix' if Puppet.features.net_http_unix_lib?
require 'socket'
require 'json'

module PuppetX
module Snap
module NetX
class HTTPUnix < Net::HTTP
BufferedIO = ::Net::BufferedIO
UNIX_REGEXP = %r{^unix://}i

def initialize(address, port=nil)
super(address, port)
case address
when UNIX_REGEXP
@socket_type = 'unix'
@socket_path = address.sub(UNIX_REGEXP, '')
# Address and port are set to localhost so the HTTP client constructs
# a HOST request header nginx will accept.
@address = 'localhost'
@port = 80
else
@socket_type = 'inet'
end
end

def connect
if @socket_type == 'unix'
connect_unix
else
super
end
end

##
# connect_unix is an alternative implementation of Net::HTTP#connect specific
# to the use case of using a Unix Domain Socket.
def connect_unix
D "opening connection to #{@socket_path}..."
s = Timeout.timeout(@open_timeout) { UNIXSocket.open(@socket_path) }
D "opened"
@socket = BufferedIO.new(s)
@socket.read_timeout = @read_timeout
@socket.continue_timeout = @continue_timeout
@socket.debug_output = @debug_output
on_connect
end
end
end

module API
class << self
%w[post put get].each do |method|
Expand All @@ -23,7 +66,7 @@ class << self
end

def call_api(request)
client = ::NetX::HTTPUnix.new('unix:///run/snapd.socket')
client = ::PuppetX::Snap::NetX::HTTPUnix.new('unix:///run/snapd.socket')

response = nil
retried = 0
Expand Down
9 changes: 1 addition & 8 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
# @param service_enable Run the system service on boot.
# @param core_snap_ensure The state of the snap `core`.
# @param manage_repo Whether we should manage EPEL repo or not.
# @param net_http_unix_ensure The state of net_http_unix gem.
class snap (
String[1] $package_ensure = 'installed',
Enum['stopped', 'running'] $service_ensure = 'running',
Boolean $service_enable = true,
String[1] $core_snap_ensure = 'installed',
Boolean $manage_repo = false,
Enum['present', 'installed', 'absent'] $net_http_unix_ensure = 'installed',
) {
if $manage_repo {
include epel
Expand All @@ -37,16 +35,11 @@
require => Package['snapd'],
}

-> package { 'net_http_unix':
ensure => $net_http_unix_ensure,
provider => 'puppet_gem',
}

if $service_ensure == 'running' {
package { 'core':
ensure => $core_snap_ensure,
provider => 'snap',
require => [Package['net_http_unix'], Service['snapd']],
require => Service['snapd'],
}
}
}
4 changes: 1 addition & 3 deletions spec/classes/init_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@

it { is_expected.to contain_package('snapd').with_ensure('installed') }
it { is_expected.to contain_service('snapd').with_ensure('running').with_enable(true).that_requires('Package[snapd]') }
it { is_expected.to contain_package('net_http_unix').with_ensure('installed').with_provider('puppet_gem').that_requires('Service[snapd]') }
it { is_expected.to contain_package('core').with_ensure('installed').with_provider('snap').that_requires(%w[Service[snapd] Package[net_http_unix]]) }
it { is_expected.to contain_package('core').with_ensure('installed').with_provider('snap').that_requires(%w[Service[snapd]]) }
end

context "on #{os} with snapd stopped" do
Expand All @@ -32,7 +31,6 @@

it { is_expected.to contain_package('snapd').with_ensure('installed') }
it { is_expected.to contain_service('snapd').with_ensure('stopped').with_enable(true).that_requires('Package[snapd]') }
it { is_expected.to contain_package('net_http_unix').with_ensure('installed').with_provider('puppet_gem').that_requires('Service[snapd]') }
it { is_expected.not_to contain_package('core').with_provider('snap') }
end
end
Expand Down
81 changes: 80 additions & 1 deletion spec/unit/puppet_x/snap/api_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,88 @@
# frozen_string_literal: true

require 'spec_helper'
require 'tempfile'
require 'puppet_x/snap/api'

module PuppetX::Snap
describe NetX::HTTPUnix do
let(:socket_url) { "unix://#{@socket_path}" }
let(:get_request) { Net::HTTP::Get.new('/') }

before :all do
tmpfile = Tempfile.open('socket')
@socket_path = tmpfile.path
tmpfile.close
tmpfile.unlink

semaphore = Mutex.new
servers_starting = 2

@server_thread_tcp = Thread.new do
TCPServer.open(2000) do |server|
semaphore.synchronize { servers_starting -= 1 }
while (conn = server.accept)
conn.puts 'HTTP/1.1 200 OK'
conn.puts ''
conn.puts 'Hello from TCP server'
conn.close_write
end
end
end

@server_thread_unix = Thread.new do
UNIXServer.open(@socket_path) do |server|
semaphore.synchronize { servers_starting -= 1 }
while (conn = server.accept)
conn.puts 'HTTP/1.1 200 OK'
conn.puts ''
conn.puts 'Hello from UNIX server'
conn.close_write
end
end
end

sleep(0.01) while servers_starting > 0
end

after :all do
Thread.kill(@server_thread_unix)
Thread.kill(@server_thread_tcp)
end

describe '.start' do
it "accepts '127.0.0.1', 2000 host and port" do
resp = described_class.start('127.0.0.1', 2000) do |http|
http.request(get_request)
end
expect(resp.body).to eq("Hello from TCP server\n")
end

it 'accepts unix:///path/to/socket URI' do
resp = described_class.start(socket_url) do |http|
http.request(get_request)
end
expect(resp.body).to eq("Hello from UNIX server\n")
end
end

describe '.new' do
it "accepts '127.0.0.1', 2000 host and port" do
http = described_class.new('127.0.0.1', 2000)

resp = http.request(get_request)
expect(resp.body).to eq("Hello from TCP server\n")
end

it 'accepts unix:///path/to/socket URI' do
http = described_class.new(socket_url)

resp = http.request(get_request)
expect(resp.body).to eq("Hello from UNIX server\n")
end
end
end

describe API do
async_change_id_res = JSON.parse(File.read('spec/fixtures/responses/async_change_id_res.json'))
error_res = JSON.parse(File.read('spec/fixtures/responses/error_res.json'))
Expand All @@ -29,7 +108,7 @@ module PuppetX::Snap
expect { described_class.complete('10') }.to raise_error(Puppet::Error)
end

it 'sleeps for 1 second if response hasn\'t completed' do
it 'sleeps for 1 second if response has not completed' do
allow(described_class).to receive(:get_status).with('10').and_return(change_status_doing, change_status_done)
allow(described_class).to receive(:sleep)
described_class.complete('10')
Expand Down