chef-api 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/chef-api.gemspec +1 -0
- data/lib/chef-api/connection.rb +171 -1
- data/lib/chef-api/version.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80b62ceb2d3f3e1b7046d2115d6b741bc983499b
|
4
|
+
data.tar.gz: ade937778aea1f66776c212918e73565ed5f1bd1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebb178741c859052b3762e52ec0d9da19b6b9bb9df52099319e028813e03b776e1ca8401dc9506bcd65a3be8a683e631c0acc89da3d1090a98a0e549e9d16b87
|
7
|
+
data.tar.gz: bd0cb8413f6add6ddac6c2f60d38a68b87d63e905a20eb2e92b36a77b7afd61d204de15242be4287e8e3d9717c38034b63fc664eae086f7823c9444281552422
|
data/CHANGELOG.md
CHANGED
data/chef-api.gemspec
CHANGED
data/lib/chef-api/connection.rb
CHANGED
@@ -204,7 +204,16 @@ module ChefAPI
|
|
204
204
|
if data.respond_to?(:read)
|
205
205
|
request.body_stream = data
|
206
206
|
elsif data.is_a?(Hash)
|
207
|
-
|
207
|
+
# If any of the values in the hash are File-like, assume this is a
|
208
|
+
# multi-part post
|
209
|
+
if data.values.any? { |value| value.respond_to?(:read) }
|
210
|
+
multipart = Multipart::Body.new(data)
|
211
|
+
request.content_length = multipart.content_length
|
212
|
+
request.content_type = multipart.content_type
|
213
|
+
request.body_stream = multipart.stream
|
214
|
+
else
|
215
|
+
request.form_data = data
|
216
|
+
end
|
208
217
|
else
|
209
218
|
request.body = data
|
210
219
|
end
|
@@ -503,4 +512,165 @@ module ChefAPI
|
|
503
512
|
end
|
504
513
|
end
|
505
514
|
end
|
515
|
+
|
516
|
+
require 'cgi'
|
517
|
+
require 'mime/types'
|
518
|
+
|
519
|
+
module Multipart
|
520
|
+
BOUNDARY = '------ChefAPIMultipartBoundary'.freeze
|
521
|
+
|
522
|
+
class Body
|
523
|
+
def initialize(params = {})
|
524
|
+
params.each do |key, value|
|
525
|
+
if value.respond_to?(:read)
|
526
|
+
parts << FilePart.new(key, value)
|
527
|
+
else
|
528
|
+
parts << ParamPart.new(key, value)
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
parts << EndingPart.new
|
533
|
+
end
|
534
|
+
|
535
|
+
def stream
|
536
|
+
MultiIO.new(*parts.map(&:io))
|
537
|
+
end
|
538
|
+
|
539
|
+
def content_type
|
540
|
+
"multipart/form-data; boundary=#{BOUNDARY}"
|
541
|
+
end
|
542
|
+
|
543
|
+
def content_length
|
544
|
+
parts.map(&:size).inject(:+)
|
545
|
+
end
|
546
|
+
|
547
|
+
private
|
548
|
+
|
549
|
+
def parts
|
550
|
+
@parts ||= []
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
class MultiIO
|
555
|
+
def initialize(*ios)
|
556
|
+
@ios = ios
|
557
|
+
@index = 0
|
558
|
+
end
|
559
|
+
|
560
|
+
# Read from IOs in order until `length` bytes have been received.
|
561
|
+
def read(length = nil, outbuf = nil)
|
562
|
+
got_result = false
|
563
|
+
outbuf = outbuf ? outbuf.replace('') : ''
|
564
|
+
|
565
|
+
while io = current_io
|
566
|
+
if result = io.read(length)
|
567
|
+
got_result ||= !result.nil?
|
568
|
+
result.force_encoding('BINARY') if result.respond_to?(:force_encoding)
|
569
|
+
outbuf << result
|
570
|
+
length -= result.length if length
|
571
|
+
break if length == 0
|
572
|
+
end
|
573
|
+
advance_io
|
574
|
+
end
|
575
|
+
|
576
|
+
(!got_result && length) ? nil : outbuf
|
577
|
+
end
|
578
|
+
|
579
|
+
def rewind
|
580
|
+
@ios.each { |io| io.rewind }
|
581
|
+
@index = 0
|
582
|
+
end
|
583
|
+
|
584
|
+
private
|
585
|
+
|
586
|
+
def current_io
|
587
|
+
@ios[@index]
|
588
|
+
end
|
589
|
+
|
590
|
+
def advance_io
|
591
|
+
@index += 1
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
#
|
596
|
+
# A generic key => value part.
|
597
|
+
#
|
598
|
+
class ParamPart
|
599
|
+
def initialize(name, value)
|
600
|
+
@part = build(name, value)
|
601
|
+
end
|
602
|
+
|
603
|
+
def io
|
604
|
+
@io ||= StringIO.new(@part)
|
605
|
+
end
|
606
|
+
|
607
|
+
def size
|
608
|
+
@part.bytesize
|
609
|
+
end
|
610
|
+
|
611
|
+
private
|
612
|
+
|
613
|
+
def build(name, value)
|
614
|
+
part = %|--#{BOUNDARY}\r\n|
|
615
|
+
part << %|Content-Disposition: form-data; name="#{CGI.escape(name)}"\r\n\r\n|
|
616
|
+
part << %|#{value}\r\n|
|
617
|
+
part
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
#
|
622
|
+
# A File part
|
623
|
+
#
|
624
|
+
class FilePart
|
625
|
+
def initialize(name, file)
|
626
|
+
@file = file
|
627
|
+
@head = build(name, file)
|
628
|
+
@foot = "\r\n"
|
629
|
+
end
|
630
|
+
|
631
|
+
def io
|
632
|
+
@io ||= MultiIO.new(
|
633
|
+
StringIO.new(@head),
|
634
|
+
@file,
|
635
|
+
StringIO.new(@foot)
|
636
|
+
)
|
637
|
+
end
|
638
|
+
|
639
|
+
def size
|
640
|
+
@head.bytesize + @file.size + @foot.bytesize
|
641
|
+
end
|
642
|
+
|
643
|
+
private
|
644
|
+
|
645
|
+
def build(name, file)
|
646
|
+
filename = File.basename(file.path)
|
647
|
+
mime_type = MIME::Types.type_for(filename)[0] || MIME::Types['application/octet-stream'][0]
|
648
|
+
|
649
|
+
part = %|--#{BOUNDARY}\r\n|
|
650
|
+
part << %|Content-Disposition: form-data; name="#{CGI.escape(name)}"; filename="#{filename}"\r\n|
|
651
|
+
part << %|Content-Length: #{file.size}\r\n|
|
652
|
+
part << %|Content-Type: #{mime_type.simplified}|
|
653
|
+
part << %|Content-Transfer-Encoding: binary\r\n|
|
654
|
+
part << %|\r\n|
|
655
|
+
part
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
#
|
660
|
+
# The end of the entire request
|
661
|
+
#
|
662
|
+
class EndingPart
|
663
|
+
def initialize
|
664
|
+
@part = "--#{BOUNDARY}--\r\n\r\n"
|
665
|
+
end
|
666
|
+
|
667
|
+
def io
|
668
|
+
@io ||= StringIO.new(@part)
|
669
|
+
end
|
670
|
+
|
671
|
+
def size
|
672
|
+
@part.bytesize
|
673
|
+
end
|
674
|
+
end
|
675
|
+
end
|
506
676
|
end
|
data/lib/chef-api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seth Vargo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06
|
11
|
+
date: 2014-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logify
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mime-types
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.3'
|
41
55
|
description: A tiny Chef API client with minimal dependencies
|
42
56
|
email:
|
43
57
|
- sethvargo@gmail.com
|
@@ -138,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
152
|
version: '0'
|
139
153
|
requirements: []
|
140
154
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.
|
155
|
+
rubygems_version: 2.3.0
|
142
156
|
signing_key:
|
143
157
|
specification_version: 4
|
144
158
|
summary: A Chef API client in Ruby
|