chef-telemetry 0.1.8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7319019f20b68bb77f02c28dcdaa9dced791613f5af25c0ad43b095f55764756
4
- data.tar.gz: 2fb617610995a63967cd6f00c500764aa45282518e77046d2c8fc3bd83cd8e39
3
+ metadata.gz: faf29c758b1dbcddd569962312d55a7f9b7648ac2fed2896a962360f62d50b93
4
+ data.tar.gz: '079575327ecc06c86e9fb305cd4e0b6339ea443ad53800006f74baa710d9f266'
5
5
  SHA512:
6
- metadata.gz: 8914e2941c35f42086f89a0bb5da066c8c069aaee72466bfc74a55d96c0972cba8c5c275aadbef3fba54eb5eb86527655fd43c6f80e007818122cef06b9b5038
7
- data.tar.gz: 06163b5ddb874c882a7c51046f4f5e34c9412e857e767fe79f2258da8ff27d93666391af58077eef2eae12b2f308cba73953fd5de56de34ea9b942c4b7b0c4f8
6
+ metadata.gz: 35a60bfa480f9085eac39bd3f1699ab2926f1c270e947439c13bfbc585e97849b5cb155bf8eaadef41496fc0a62c13867dc25b3380ece12d1460e84fee8794aa
7
+ data.tar.gz: 4bd4017b173ba7a50f5888550c16e1b0616c0a2b6176ba719513bad27ece43ce32dca9208ad7a891e519e3d957e64c26ce8ef56e20ca2eace83383c743b81592
@@ -0,0 +1,162 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2018 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "chef/telemetry/version"
19
+ require "benchmark"
20
+ require "forwardable"
21
+ require "singleton"
22
+ require "json"
23
+ require "digest/sha1"
24
+ require "securerandom"
25
+ require "yaml"
26
+
27
+ module Chef
28
+ # This definites the Telemeter interface. Implementation thoughts for
29
+ # when we unstub it:
30
+ # - let's track the call sequence; most of our calls will be nested inside
31
+ # a main 'timed_capture', and it would be good to see ordering within nested calls.
32
+ class Telemeter
33
+ include Singleton
34
+ DEFAULT_INSTALLATION_GUID = "00000000-0000-0000-0000-000000000000".freeze
35
+
36
+ class << self
37
+ extend Forwardable
38
+ def_delegators :instance, :setup, :timed_capture, :capture, :commit, :timed_run_capture
39
+ def_delegators :instance, :pending_event_count, :last_event, :enabled?
40
+ def_delegators :instance, :make_event_payload, :config
41
+ end
42
+
43
+ attr_reader :events_to_send, :run_timestamp, :config
44
+
45
+ def setup(config)
46
+ # TODO validate required & correct keys
47
+ # :payload_dir #required
48
+ # :session_file # required
49
+ # :installation_identifier_file # required
50
+ # :enabled # false, not required
51
+ # :dev_mode # false, not required
52
+ config[:dev_mode] ||= false
53
+ config[:enabled] ||= false
54
+ require "chef_core/telemeter/sender"
55
+ @config = config
56
+ Sender.start_upload_thread(config)
57
+ end
58
+
59
+ def enabled?
60
+ require "chef/telemetry/decision"
61
+ config[:enabled] && !Telemetry::Decision.env_opt_out?
62
+ end
63
+
64
+ def initialize
65
+ @events_to_send = []
66
+ @run_timestamp = Time.now.utc.strftime("%FT%TZ")
67
+ end
68
+
69
+ def timed_run_capture(arguments, &block)
70
+ timed_capture(:run, arguments: arguments, &block)
71
+ end
72
+
73
+ def timed_capture(name, data = {}, options = {})
74
+ time = Benchmark.measure { yield }
75
+ data[:duration] = time.real
76
+ capture(name, data, options)
77
+ end
78
+
79
+ def capture(name, data = {}, options = {})
80
+ # Adding it to the head of the list will ensure that the
81
+ # sequence of events is preserved when we send the final payload
82
+ payload = make_event_payload(name, data, options)
83
+ @events_to_send.unshift payload
84
+ end
85
+
86
+ def commit
87
+ if enabled?
88
+ session = convert_events_to_session
89
+ write_session(session)
90
+ end
91
+ @events_to_send = []
92
+ end
93
+
94
+ def make_event_payload(name, data, options = {})
95
+ payload = {
96
+ event: name,
97
+ properties: {
98
+ installation_id: installation_id,
99
+ run_timestamp: run_timestamp,
100
+ host_platform: host_platform,
101
+ },
102
+ }
103
+ if options[:flatten]
104
+ payload[:properties].merge! data
105
+ else
106
+ payload[:properties][:event_data] = data
107
+ end
108
+ payload
109
+ end
110
+
111
+ def installation_id
112
+ @installation_id ||=
113
+ begin
114
+ File.read(config[:installation_identifier_file]).chomp
115
+ rescue
116
+ Telemeter::Log.info "could not read #{config[:installation_identifier_file]} - using default id"
117
+ DEFAULT_INSTALLATION_GUID
118
+ end
119
+ end
120
+
121
+ # For testing.
122
+ def pending_event_count
123
+ @events_to_send.length
124
+ end
125
+
126
+ def last_event
127
+ @events_to_send.last
128
+ end
129
+
130
+ private
131
+
132
+ def host_platform
133
+ @host_platform ||= case RUBY_PLATFORM
134
+ when /mswin|mingw|windows/
135
+ "windows"
136
+ else
137
+ RUBY_PLATFORM.split("-")[1]
138
+ end
139
+ end
140
+
141
+ def convert_events_to_session
142
+ YAML.dump("version" => Telemetry::VERSION,
143
+ "entries" => @events_to_send)
144
+ end
145
+
146
+ def write_session(session)
147
+ File.write(next_filename, convert_events_to_session)
148
+ end
149
+
150
+ def next_filename
151
+ id = 0
152
+ filename = ""
153
+ loop do
154
+ id += 1
155
+ filename = File.join(config[:payload_dir], "telemetry-payload-#{id}.yml")
156
+ break unless File.exist?(filename)
157
+ end
158
+ filename
159
+ end
160
+
161
+ end
162
+ end # Chef
@@ -0,0 +1,125 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2018 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "chef/telemetry"
19
+ require "chef/telemeter"
20
+ require "logger"
21
+
22
+ module Chef
23
+ class Telemeter
24
+ logger = ::Logger.new(STDERR) # TODO: maybe switch to file, maybe switch to mixlib
25
+ logger.level = Logger::ERROR
26
+ Log = logger # rubocop:disable Naming/ConstantName
27
+
28
+ class Sender
29
+ attr_reader :session_files, :config
30
+
31
+ def self.start_upload_thread(config)
32
+ # Find the files before we spawn the thread - otherwise
33
+ # we may accidentally pick up the current run's session file if it
34
+ # finishes before the thread scans for new files
35
+ session_files = Sender.find_session_files(config)
36
+ sender = Sender.new(session_files, config)
37
+ Thread.new { sender.run }
38
+ end
39
+
40
+ def self.find_session_files(config)
41
+ Telemeter::Log.info("Looking for telemetry data to submit")
42
+ session_search = File.join(config[:payload_dir], "telemetry-payload-*.yml")
43
+ session_files = Dir.glob(session_search)
44
+ Telemeter::Log.info("Found #{session_files.length} sessions to submit")
45
+ session_files
46
+ end
47
+
48
+ def initialize(session_files, config)
49
+ @session_files = session_files
50
+ @config = config
51
+ end
52
+
53
+ def run
54
+ if Telemeter.enabled?
55
+ Telemeter::Log.info("Telemetry enabled, beginning upload of previous session(s)")
56
+ # dev mode telemetry gets sent to a different location
57
+
58
+ if config[:dev_mode]
59
+ ENV["CHEF_TELEMETRY_ENDPOINT"] ||= "https://telemetry-acceptance.chef.io"
60
+ end
61
+ session_files.each { |path| process_session(path) }
62
+ else
63
+ # If telemetry is not enabled, just clean up and return. Even though
64
+ # the telemetry gem will not send if disabled, log output saying that we're submitting
65
+ # it when it has been disabled can be alarming.
66
+ Telemeter::Log.info("Telemetry disabled, clearing any existing session captures without sending them.")
67
+ session_files.each { |path| FileUtils.rm_rf(path) }
68
+ end
69
+ FileUtils.rm_rf(config[:session_file])
70
+ Telemeter::Log.info("Terminating, nothing more to do.")
71
+ rescue => e
72
+ Telemeter::Log.fatal "Sender thread aborted: '#{e}' failed at #{e.backtrace[0]}"
73
+ end
74
+
75
+ def process_session(path)
76
+ Telemeter::Log.info("Processing telemetry entries from #{path}")
77
+ content = load_and_clear_session(path)
78
+ submit_session(content)
79
+ end
80
+
81
+ def submit_session(content)
82
+ # Each file contains the actions taken within a single run of the chef tool.
83
+ # Each run is one session, so we'll first remove remove the session file
84
+ # to force creating a new one.
85
+ FileUtils.rm_rf(config[:session_file])
86
+ # We'll use the version captured in the sesion file
87
+ entries = content["entries"]
88
+ total = entries.length
89
+ product_info = config[:product] || {}
90
+ telemetry = Telemetry.new(product: product_info[:name] || "chef-workstation",
91
+ origin: product_info[:origin] || "command-line",
92
+ product_version: product_info[:version] || content["version"],
93
+ install_context: product_info[:install_context] || "omnibus")
94
+ total = entries.length
95
+ entries.each_with_index do |entry, x|
96
+ submit_entry(telemetry, entry, x + 1, total)
97
+ end
98
+ end
99
+
100
+ def submit_entry(telemetry, entry, sequence, total)
101
+ Telemeter::Log.info("Submitting telemetry entry #{sequence}/#{total}: #{entry} ")
102
+ telemetry.deliver(entry)
103
+ Telemeter::Log.info("Entry #{sequence}/#{total} submitted.")
104
+ rescue => e
105
+ # No error handling in telemetry lib, so at least track the failrue
106
+ Telemeter::Log.error("Failed to send entry #{sequence}/#{total}: #{e}")
107
+ Telemeter::Log.error("Backtrace: #{e.backtrace} ")
108
+ end
109
+
110
+ private
111
+
112
+ def load_and_clear_session(path)
113
+ content = File.read(path)
114
+ # We'll remove it now instead of after we parse or submit it -
115
+ # if we fail to deliver, we don't want to be stuck resubmitting it if the problem
116
+ # was due to payload. This is a trade-off - if we get a transient error, the
117
+ # payload will be lost.
118
+ # TODO: Improve error handling so we can intelligently decide whether to
119
+ # retry a failed load or failed submit.
120
+ FileUtils.rm_rf(path)
121
+ YAML.load(content)
122
+ end
123
+ end
124
+ end
125
+ end # Chef
@@ -0,0 +1,45 @@
1
+ require "chef/telemetry/client"
2
+ require "chef/telemetry/decision"
3
+ require "chef/telemetry/event"
4
+ require "chef/telemetry/session"
5
+ require "chef/telemetry/version"
6
+
7
+ module Chef
8
+ class Telemetry
9
+ attr_accessor :product, :origin, :product_version, :install_context
10
+ def initialize(product: nil, origin: "command-line",
11
+ product_version: "0.0.0",
12
+ install_context: "omnibus")
13
+ # Reference: https://github.com/chef/es-telemetry-pipeline/blob/0730c1e2605624a50d34bab6d036b73c31e0ab0e/schema/event.schema.json#L77
14
+ @product = product
15
+ @origin = origin
16
+ @product_version = product_version
17
+ @install_context = install_context # Valid: habitat, omnibus
18
+ end
19
+
20
+ def deliver(data = {})
21
+ unless opt_out?
22
+ payload = event.prepare(data)
23
+ client.await.fire(payload)
24
+ end
25
+ end
26
+
27
+ def event
28
+ @event ||= Event.new(product, session, origin,
29
+ install_context, product_version)
30
+ end
31
+
32
+ def session
33
+ @session ||= Session.new
34
+ end
35
+
36
+ def opt_out?
37
+ @opt_out ||= Decision.opt_out?
38
+ end
39
+
40
+ def client
41
+ endpoint = ENV.fetch("CHEF_TELEMETRY_ENDPOINT", Client::TELEMETRY_ENDPOINT)
42
+ @client ||= Client.new(endpoint)
43
+ end
44
+ end
45
+ end # Chef
@@ -0,0 +1,26 @@
1
+ require "http"
2
+ require "concurrent"
3
+
4
+ module Chef
5
+ class Telemetry
6
+ class Client
7
+ include Concurrent::Async
8
+
9
+ TELEMETRY_ENDPOINT = "https://telemetry.chef.io".freeze
10
+
11
+ attr_reader :http
12
+ def initialize(endpoint = TELEMETRY_ENDPOINT)
13
+ super()
14
+ @http = HTTP.persistent(endpoint)
15
+ end
16
+
17
+ def fire(event)
18
+ http.post("/events", json: event).flush
19
+ end
20
+ end
21
+
22
+ class OptOutClient
23
+ def fire(_); end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,67 @@
1
+ require "chef-config/path_helper"
2
+ require "chef-config/windows"
3
+
4
+ # Decision allows us to inspect whether the user has made a decision to opt in or opt out of telemetry.
5
+ module Chef
6
+ class Telemetry
7
+ module Decision
8
+ OPT_OUT_FILE = "telemetry_opt_out".freeze
9
+ OPT_IN_FILE = "telemetry_opt_in".freeze
10
+
11
+ class << self
12
+ def opt_out?
13
+ # We check that the user has made a decision so that we can have a default setting for robots
14
+ user_opted_out? || env_opt_out? || local_opt_out? || !made?
15
+ end
16
+
17
+ # Check whether the user has made an explicit decision on their participation.
18
+ def made?
19
+ user_opted_in? || user_opted_out?
20
+ end
21
+
22
+ def user_opted_out?
23
+ File.exist?(File.join(home, OPT_OUT_FILE))
24
+ end
25
+
26
+ def user_opted_in?
27
+ File.exist?(File.join(home, OPT_IN_FILE))
28
+ end
29
+
30
+ def env_opt_out?
31
+ ENV.key?("CHEF_TELEMETRY_OPT_OUT")
32
+ end
33
+
34
+ def local_opt_out?
35
+ found = false
36
+ full_path = working_directory.split(File::SEPARATOR)
37
+ (full_path.length - 1).downto(0) do |i|
38
+ candidate = File.join(full_path[0..i], ".chef", OPT_OUT_FILE)
39
+ if File.exist?(candidate)
40
+ # TODO: push up logging
41
+ # Log.info "Found opt out at: #{candidate}"
42
+ found = true
43
+ break
44
+ end
45
+ end
46
+ found
47
+ end
48
+
49
+ private
50
+
51
+ def working_directory
52
+ a = if ChefConfig.windows?
53
+ ENV["CD"]
54
+ else
55
+ ENV["PWD"]
56
+ end || Dir.pwd
57
+
58
+ a
59
+ end
60
+
61
+ def home
62
+ ChefConfig::PathHelper.home(".chef")
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end # Chef
@@ -0,0 +1,44 @@
1
+ module Chef
2
+ class Telemetry
3
+ class Event
4
+
5
+ SKELETON = {
6
+ instance_id: "00000000-0000-0000-0000-000000000000",
7
+ message_version: 1.0,
8
+ payload_version: 1.0,
9
+ license_id: "00000000-0000-0000-0000-000000000000",
10
+ type: "track",
11
+ }.freeze
12
+
13
+ attr_reader :session, :product, :origin,
14
+ :product_version, :install_context
15
+ def initialize(product, session, origin = "command-line",
16
+ install_context = "omnibus", product_version = "0.0.0")
17
+ @product = product
18
+ @session = session
19
+ @origin = origin
20
+ @product_version = product_version
21
+ @install_context = install_context
22
+ end
23
+
24
+ def prepare(event)
25
+ time = timestamp
26
+ event[:properties][:timestamp] = time
27
+ body = SKELETON.dup
28
+ body.tap do |b|
29
+ b[:session_id] = session.id
30
+ b[:origin] = origin
31
+ b[:product] = product
32
+ b[:product_version] = product_version
33
+ b[:install_context] = install_context
34
+ b[:timestamp] = time
35
+ b[:payload] = event
36
+ end
37
+ end
38
+
39
+ def timestamp
40
+ Time.now.utc.strftime("%FT%TZ")
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,39 @@
1
+ require "securerandom"
2
+ require "chef-config/path_helper"
3
+
4
+ module Chef
5
+ class Telemetry
6
+ class Session
7
+ def initialize
8
+ @id = if live_session?
9
+ File.read(session_file).chomp
10
+ else
11
+ new_session
12
+ end
13
+ end
14
+
15
+ def id
16
+ FileUtils.touch(session_file)
17
+ @id
18
+ end
19
+
20
+ private
21
+
22
+ def live_session?
23
+ expiry = Time.now - 600
24
+ File.file?(session_file) && File.stat(session_file).mtime > expiry
25
+ end
26
+
27
+ def session_file
28
+ File.join(ChefConfig::PathHelper.home(".chef"), "TELEMETRY_SESSION_ID").freeze
29
+ end
30
+
31
+ def new_session
32
+ id = SecureRandom.uuid
33
+ FileUtils.mkdir_p(File.dirname(session_file))
34
+ File.open(session_file, "w") { |f| f.write(id) }
35
+ id
36
+ end
37
+ end
38
+ end
39
+ end # Chef
@@ -0,0 +1,5 @@
1
+ module Chef
2
+ class Telemetry
3
+ VERSION = "1.0.0".freeze
4
+ end
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-telemetry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef Software, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-16 00:00:00.000000000 Z
11
+ date: 2019-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -87,12 +87,14 @@ extensions: []
87
87
  extra_rdoc_files: []
88
88
  files:
89
89
  - LICENSE
90
- - lib/telemetry.rb
91
- - lib/telemetry/client.rb
92
- - lib/telemetry/decision.rb
93
- - lib/telemetry/event.rb
94
- - lib/telemetry/session.rb
95
- - lib/telemetry/version.rb
90
+ - lib/chef/telemeter.rb
91
+ - lib/chef/telemeter/sender.rb
92
+ - lib/chef/telemetry.rb
93
+ - lib/chef/telemetry/client.rb
94
+ - lib/chef/telemetry/decision.rb
95
+ - lib/chef/telemetry/event.rb
96
+ - lib/chef/telemetry/session.rb
97
+ - lib/chef/telemetry/version.rb
96
98
  homepage: https://github.com/chef/chef-telemetry
97
99
  licenses:
98
100
  - Apache-2.0
@@ -112,8 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
114
  - !ruby/object:Gem::Version
113
115
  version: '0'
114
116
  requirements: []
115
- rubyforge_project:
116
- rubygems_version: 2.7.6
117
+ rubygems_version: 3.0.3
117
118
  signing_key:
118
119
  specification_version: 4
119
120
  summary: Send user actions to the Chef telemetry system. See Chef RFC-051 for further
@@ -1,43 +0,0 @@
1
- require "telemetry/client"
2
- require "telemetry/decision"
3
- require "telemetry/event"
4
- require "telemetry/session"
5
- require "telemetry/version"
6
-
7
- class Telemetry
8
- attr_accessor :product, :origin, :product_version, :install_context
9
- def initialize(product: nil, origin: "command-line",
10
- product_version: "0.0.0",
11
- install_context: "omnibus")
12
- # Reference: https://github.com/chef/es-telemetry-pipeline/blob/0730c1e2605624a50d34bab6d036b73c31e0ab0e/schema/event.schema.json#L77
13
- @product = product
14
- @origin = origin
15
- @product_version = product_version
16
- @install_context = install_context # Valid: habitat, omnibus
17
- end
18
-
19
- def deliver(data = {})
20
- unless opt_out?
21
- payload = event.prepare(data)
22
- client.await.fire(payload)
23
- end
24
- end
25
-
26
- def event
27
- @event ||= Event.new(product, session, origin,
28
- install_context, product_version)
29
- end
30
-
31
- def session
32
- @session ||= Session.new
33
- end
34
-
35
- def opt_out?
36
- @opt_out ||= Decision.opt_out?
37
- end
38
-
39
- def client
40
- endpoint = ENV.fetch("CHEF_TELEMETRY_ENDPOINT", Client::TELEMETRY_ENDPOINT)
41
- @client ||= Client.new(endpoint)
42
- end
43
- end
@@ -1,24 +0,0 @@
1
- require "http"
2
- require "concurrent"
3
-
4
- class Telemetry
5
- class Client
6
- include Concurrent::Async
7
-
8
- TELEMETRY_ENDPOINT = "https://telemetry.chef.io".freeze
9
-
10
- attr_reader :http
11
- def initialize(endpoint = TELEMETRY_ENDPOINT)
12
- super()
13
- @http = HTTP.persistent(endpoint)
14
- end
15
-
16
- def fire(event)
17
- http.post("/events", json: event).flush
18
- end
19
- end
20
-
21
- class OptOutClient
22
- def fire(_); end
23
- end
24
- end
@@ -1,64 +0,0 @@
1
- require "chef-config/path_helper"
2
- require "chef-config/windows"
3
-
4
- # Decision allows us to inspect whether the user has made a decision to opt in or opt out of telemetry.
5
- class Telemetry
6
- module Decision
7
- OPT_OUT_FILE = "telemetry_opt_out".freeze
8
- OPT_IN_FILE = "telemetry_opt_in".freeze
9
-
10
- class << self
11
- def opt_out?
12
- # We check that the user has made a decision so that we can have a default setting for robots
13
- user_opted_out? || env_opt_out? || local_opt_out? || !made?
14
- end
15
-
16
- # Check whether the user has made an explicit decision on their participation.
17
- def made?
18
- user_opted_in? || user_opted_out?
19
- end
20
-
21
- def user_opted_out?
22
- File.exist?(File.join(home, OPT_OUT_FILE))
23
- end
24
-
25
- def user_opted_in?
26
- File.exist?(File.join(home, OPT_IN_FILE))
27
- end
28
-
29
- def env_opt_out?
30
- ENV.key?("CHEF_TELEMETRY_OPT_OUT")
31
- end
32
-
33
- def local_opt_out?
34
- found = false
35
- full_path = working_directory.split(File::SEPARATOR)
36
- (full_path.length - 1).downto(0) do |i|
37
- candidate = File.join(full_path[0..i], ".chef", OPT_OUT_FILE)
38
- if File.exist?(candidate)
39
- puts "Found opt out at: #{candidate}"
40
- found = true
41
- break
42
- end
43
- end
44
- found
45
- end
46
-
47
- private
48
-
49
- def working_directory
50
- a = if ChefConfig.windows?
51
- ENV["CD"]
52
- else
53
- ENV["PWD"]
54
- end || Dir.pwd
55
-
56
- a
57
- end
58
-
59
- def home
60
- ChefConfig::PathHelper.home(".chef")
61
- end
62
- end
63
- end
64
- end
@@ -1,42 +0,0 @@
1
- class Telemetry
2
- class Event
3
-
4
- SKELETON = {
5
- instance_id: "00000000-0000-0000-0000-000000000000",
6
- message_version: 1.0,
7
- payload_version: 1.0,
8
- license_id: "00000000-0000-0000-0000-000000000000",
9
- type: "track",
10
- }.freeze
11
-
12
- attr_reader :session, :product, :origin,
13
- :product_version, :install_context
14
- def initialize(product, session, origin = "command-line",
15
- install_context = "omnibus", product_version = "0.0.0")
16
- @product = product
17
- @session = session
18
- @origin = origin
19
- @product_version = product_version
20
- @install_context = install_context
21
- end
22
-
23
- def prepare(event)
24
- time = timestamp
25
- event[:properties][:timestamp] = time
26
- body = SKELETON.dup
27
- body.tap do |b|
28
- b[:session_id] = session.id
29
- b[:origin] = origin
30
- b[:product] = product
31
- b[:product_version] = product_version
32
- b[:install_context] = install_context
33
- b[:timestamp] = time
34
- b[:payload] = event
35
- end
36
- end
37
-
38
- def timestamp
39
- Time.now.utc.strftime("%FT%TZ")
40
- end
41
- end
42
- end
@@ -1,37 +0,0 @@
1
- require "securerandom"
2
- require "chef-config/path_helper"
3
-
4
- class Telemetry
5
- class Session
6
- def initialize
7
- @id = if live_session?
8
- File.read(session_file).chomp
9
- else
10
- new_session
11
- end
12
- end
13
-
14
- def id
15
- FileUtils.touch(session_file)
16
- @id
17
- end
18
-
19
- private
20
-
21
- def live_session?
22
- expiry = Time.now - 600
23
- File.file?(session_file) && File.stat(session_file).mtime > expiry
24
- end
25
-
26
- def session_file
27
- File.join(ChefConfig::PathHelper.home(".chef"), "TELEMETRY_SESSION_ID").freeze
28
- end
29
-
30
- def new_session
31
- id = SecureRandom.uuid
32
- FileUtils.mkdir_p(File.dirname(session_file))
33
- File.open(session_file, "w") { |f| f.write(id) }
34
- id
35
- end
36
- end
37
- end
@@ -1,3 +0,0 @@
1
- class Telemetry
2
- VERSION = "0.1.8".freeze
3
- end