kubetailrb 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b945e0de1dfdd765db891edb1a5e8c59a6cf7c1940a81147a4cd3c31b398003
4
- data.tar.gz: bbebd5de583b686f18750f26bb2b9b52f3505da68285286e91f20417c0ecfa23
3
+ metadata.gz: '0916dd6a8baf85b2f7b4771e9d0623fdbe1ff22ca0ea4111cc54ba1fcfab7fd4'
4
+ data.tar.gz: 051cc8d7bae42f86ce12b2ac43a567674d187170c73f5079aee14f66cb91a44b
5
5
  SHA512:
6
- metadata.gz: 871dc15cb59a8b657d4488fa08f78a04db28910b9aac8ff1938944d943d7a9a99b895164d6fe39f1ce8541a41730da3e34a84c09a89486bf73c2870fea13885d
7
- data.tar.gz: 86d562f6163e7206a5c7a95f52bf8dd2e56de246590b35b4fdd338c1bc1624aacdbd2a7df91475f9612e737e320bdc7ba53ea86cb7bdb0f54ea6d0c89baaf6fc
6
+ metadata.gz: 35a876c94e0a0c812e92d9e1828996c186a7e9179ada8222265ee30925cb20d91ea67f0047661df4c87eb0508b26752ee50de37ef5078740288bb6cb75c38214
7
+ data.tar.gz: 776f10f0896164550dee36bdae375852b8e374aef9d304c5ddde313202c809fa59ffcf46dbc5a7252464425b695cc62f1536895874c0c4ceeed242d8c41a6763
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
- ## [Unreleased]
1
+ ## [0.3.0] - 2024-12-11
2
+
3
+ - rename `--exclude` flag to `--excludes`
4
+ - add `--mdcs` flag to include specific MDCs
5
+
6
+ ## [0.2.0] - 2024-12-05
7
+
8
+ - remove `--pretty` flag
9
+ - now by default, it's displayed in pretty mode
10
+ - to display the log without formatting, use `--raw` flag
11
+ - add possibility to filter out the access and datadog logs
12
+ - support displaying stack trace in pretty mode
13
+ - support formatting rails logs
14
+ - fix color when receiving HTTP 500 in access logs
15
+ - add `--display-names` flag to display the pod and container names
16
+ - colorize pod events (blue for new pod events, red for deleted pod events)
2
17
 
3
18
  ## [0.1.0] - 2024-10-27
4
19
 
5
20
  - Initial release
21
+
22
+ ## [Unreleased]
data/README.md CHANGED
@@ -1,21 +1,20 @@
1
1
  # Kubetailrb
2
2
 
3
- > Tail your Kubernetes pod logs at the same time.
3
+ [![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/HazAT/badge/blob/master/LICENSE)
4
+ [![Gem](https://img.shields.io/gem/v/kubetailrb?style=flat)](http://rubygems.org/gems/kubetailrb)
4
5
 
5
- > [!NOTE]
6
- > This project is a pet project I used to learn the [Ruby programming language](https://www.ruby-lang.org/en/).
7
- > So you might find lots of my [personal notes](./journey_log.md) in the codebase.
8
- >
9
- > If you want to have something that works, please look at the following
10
- > projects that were used as inspirations instead:
11
- >
12
- > - https://github.com/stern/stern
13
- > - https://github.com/johanhaleby/kubetail
6
+ > Tail your Kubernetes pod logs at the same time.
14
7
 
15
8
  ![kubetailrb](./kubetailrb.png)
16
9
 
17
10
  ## Installation
18
11
 
12
+ ```sh
13
+ gem install kubetailrb
14
+ ```
15
+
16
+ If you want to install directly from the repository instead:
17
+
19
18
  ```sh
20
19
  # Install dependencies.
21
20
  ./bin/setup
@@ -31,16 +30,28 @@ bundle exec rake install
31
30
  kubetailrb -h
32
31
 
33
32
  # follow pod logs
34
- kubetailrb 'clock' --namespace sandbox
33
+ kubetailrb 'clock' --namespace sandbox --raw
35
34
 
36
35
  # follow pod structured JSON logs and display in human friendly way
37
- kubetailrb 'clock-json' --namespace sandbox --pretty --raw --follow
36
+ kubetailrb 'clock-json' --namespace sandbox --follow
38
37
  # or with shorter flags
39
- kubetailrb 'clock-json' -n sandbox -p -r -f
38
+ kubetailrb 'clock-json' -n sandbox -f
40
39
 
41
40
  # you can filter the pods using regex on the pod names
42
- kubetailrb '^clock(?!-json)' -n sandbox -p -r
41
+ kubetailrb '^clock(?!-json)' -n sandbox -f
42
+
43
+ # you can also filter the containers using regex on the container names
44
+ kubetailrb 'clock' -n sandbox -f -c 'my-container'
43
45
 
46
+ # you can exclude access logs
47
+ kubetailrb 'clock' -n sandbox -f --excludes access-logs
48
+ # or Datadog logs
49
+ kubetailrb 'clock' -n sandbox -f --excludes dd-logs
50
+ # or both
51
+ kubetailrb 'clock' -n sandbox -f --excludes access-logs,dd-logs
52
+
53
+ # you can include your MDCs by adding your MDC names separated by a comma
54
+ kubetailrb 'clock' -n sandbox -f --mdcs thread.name,service.version
44
55
  ```
45
56
 
46
57
  ## Development
@@ -64,10 +75,34 @@ bundle exec rake test:watch
64
75
  bundle exec rake
65
76
  ```
66
77
 
78
+ ## Release a new version
79
+
80
+ Update the version in
81
+ [`lib/kubetailrb/version.rb`](./lib/kubetailrb/version.rb).
82
+
83
+ > [!WARNING]
84
+ > You may have to update the tests...
85
+ > Too lazy to update the script to also update the tests...
86
+
87
+ Then execute the script:
88
+
89
+ ```sh
90
+ ./bin/release
91
+ ```
92
+
67
93
  ## Contributing
68
94
 
69
95
  Bug reports and pull requests are welcome on GitHub at https://github.com/l-lin/kubetailrb.
70
96
 
97
+ ## Note
98
+
99
+ This project is a pet project I used to learn the [Ruby programming language](https://www.ruby-lang.org/en/).
100
+ So you might find lots of my [personal notes](./journey_log.md) in the codebase.
101
+
102
+ If you want to have something that is more complete, please look at
103
+ [stern](https://github.com/stern/stern) project that was used as inspirations
104
+ instead.
105
+
71
106
  ## License
72
107
 
73
108
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -66,6 +66,17 @@ namespace :k8s do
66
66
  puts `kubectl run #{app_name} --image #{docker_image}`
67
67
  end
68
68
 
69
+ desc 'Delete application from k8s.'
70
+ task :delete, [:app_name] do |_, args|
71
+ next unless k8s_up?
72
+
73
+ app_name = args[:app_name]
74
+
75
+ next if app_name.nil? || app_name.strip.empty?
76
+
77
+ puts `kubectl delete po #{app_name} --force true` if pod_up?(app_name)
78
+ end
79
+
69
80
  desc 'Deploy all applications to k8s.'
70
81
  task :deploy_all do
71
82
  Rake::Task['k8s:deploy'].invoke('clock')
data/journey_log.md CHANGED
@@ -4,12 +4,6 @@
4
4
  > tribulations, and triumphs as I navigated the world of this dynamic
5
5
  > programming language.
6
6
 
7
-
8
- ## 🤔 Things that I'm curious about
9
-
10
-
11
- ---
12
-
13
7
  ## 2024-10-27
14
8
  ### Context
15
9
 
@@ -90,7 +84,7 @@ It seems the convention is:
90
84
  - `features` contains the cucumber scenarios, i.e. integration tests.
91
85
  - `bin/` contains some scripts that can help the developer experience,
92
86
  - Rails projects also have scripts in this `bin/` directory.
93
- - `exec/` contains the executables that will be installed to the user system if
87
+ - `exe/` contains the executables that will be installed to the user system if
94
88
  the latter is installing the gem
95
89
  - It seems to be a convention from Bundler, but that is configurable in the
96
90
  `gemspec` file.
data/kubetailrb.png CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'kubetailrb/file_reader'
3
+ require 'kubetailrb/reader/file_reader'
4
4
 
5
5
  module Kubetailrb
6
6
  module Cmd
@@ -13,7 +13,7 @@ module Kubetailrb
13
13
  attr_reader :reader
14
14
 
15
15
  def initialize(filepath:, last_nb_lines: DEFAULT_NB_LINES, follow: DEFAULT_FOLLOW)
16
- @reader = Kubetailrb::FileReader.new(filepath: filepath, last_nb_lines: last_nb_lines, follow: follow)
16
+ @reader = Kubetailrb::Reader::FileReader.new(filepath: filepath, last_nb_lines: last_nb_lines, follow: follow)
17
17
  end
18
18
 
19
19
  def execute
@@ -14,14 +14,17 @@ module Kubetailrb
14
14
  kubetailrb pod-query [flags]
15
15
 
16
16
  Flags:
17
- -v, --version Display version.
18
- -h, --help Display help.
19
- --tail The number of lines from the end of the logs to show. Defaults to 10.
20
- -f, --follow Output appended data as the file grows.
21
- --file Display file content.
22
- -p, --pretty Pretty print JSON logs.
23
- -r, --raw Only display pod logs.
24
- -n, --namespace Kubernetes namespace to use.
17
+ -v, --version Display version.
18
+ -h, --help Display help.
19
+ --tail The number of lines from the end of the logs to show. Defaults to 10.
20
+ -f, --follow Output appended data as the file grows.
21
+ --file Display file content.
22
+ -r, --raw Only display pod logs, without any special formatting.
23
+ --display-names Display pod and container names.
24
+ -n, --namespace Kubernetes namespace to use.
25
+ -c, --container Container name when multiple containers in pod. Default to '.'.
26
+ -e, --excludes Exclude types of log, separated by a comma. Supporting only 'access-logs' and 'dd-logs'.
27
+ -m, --mdcs Include MDCs if present in the JSON log, separated by a comma. E.g. 'account.id,thread.name'.
25
28
  HELP
26
29
  end
27
30
 
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'kubetailrb/k8s_pods_reader'
4
- require 'kubetailrb/json_formatter'
5
- require 'kubetailrb/no_op_formatter'
3
+ require 'kubetailrb/reader/k8s_pods_reader'
6
4
 
7
5
  module Kubetailrb
8
6
  module Cmd
@@ -10,17 +8,27 @@ module Kubetailrb
10
8
  class K8s
11
9
  DEFAULT_NB_LINES = 10
12
10
  DEFAULT_NAMESPACE = 'default'
11
+ DEFAULT_CONTAINER_QUERY = '.*'
13
12
 
14
13
  NAMESPACE_FLAGS = %w[-n --namespace].freeze
15
14
  TAIL_FLAG = '--tail'
16
15
  FOLLOW_FLAGS = %w[-f --follow].freeze
17
16
  RAW_FLAGS = %w[-r --raw].freeze
18
- PRETTY_PRINT_FLAGS = %w[-p --pretty].freeze
17
+ DISPLAY_NAMES_FLAG = '--display-names'
18
+
19
+ CONTAINER_FLAGS = %w[-c --container].freeze
20
+ EXCLUDES_FLAGS = %w[-e --excludes].freeze
21
+
22
+ MDCS_FLAGS = %w[-m --mdcs].freeze
19
23
 
20
24
  attr_reader :reader
21
25
 
22
- def initialize(pod_query:, opts:, formatter:)
23
- @reader = Kubetailrb::K8sPodsReader.new(pod_query: pod_query, formatter: formatter, opts: opts)
26
+ def initialize(pod_query:, container_query:, opts:)
27
+ @reader = Kubetailrb::Reader::K8sPodsReader.new(
28
+ pod_query: pod_query,
29
+ container_query: container_query,
30
+ opts: opts
31
+ )
24
32
  end
25
33
 
26
34
  def execute
@@ -31,12 +39,15 @@ module Kubetailrb
31
39
  def create(*args)
32
40
  new(
33
41
  pod_query: parse_pod_query(*args),
34
- formatter: parse_pretty_print(*args) ? Kubetailrb::JsonFormatter.new : Kubetailrb::NoOpFormatter.new,
42
+ container_query: parse_container_query(*args),
35
43
  opts: K8sOpts.new(
36
44
  namespace: parse_namespace(*args),
37
45
  last_nb_lines: parse_nb_lines(*args),
38
46
  follow: parse_follow(*args),
39
- raw: parse_raw(*args)
47
+ raw: parse_raw(*args),
48
+ display_names: parse_display_names(*args),
49
+ excludes: parse_excludes(*args),
50
+ mdcs: parse_mdcs(*args)
40
51
  )
41
52
  )
42
53
  end
@@ -57,7 +68,7 @@ module Kubetailrb
57
68
  #
58
69
  # will return 'sandbox'.
59
70
  #
60
- # Will raise `MissingNamespaceValueError` if the value is not provided:
71
+ # Will raise `ArgumentError` if the value is not provided:
61
72
  #
62
73
  # kubetailrb some-pod -n
63
74
  #
@@ -66,7 +77,7 @@ module Kubetailrb
66
77
 
67
78
  index = args.find_index { |arg| NAMESPACE_FLAGS.include?(arg) }.to_i
68
79
 
69
- raise MissingNamespaceValueError, "Missing #{NAMESPACE_FLAGS} value." if args[index + 1].nil?
80
+ raise ArgumentError, "Missing #{NAMESPACE_FLAGS} value." if args[index + 1].nil?
70
81
 
71
82
  args[index + 1]
72
83
  end
@@ -78,11 +89,11 @@ module Kubetailrb
78
89
  #
79
90
  # will return 3.
80
91
  #
81
- # Will raise `MissingNbLinesValueError` if the value is not provided:
92
+ # Will raise `ArgumentError` if the value is not provided:
82
93
  #
83
94
  # kubetailrb some-pod --tail
84
95
  #
85
- # Will raise `InvalidNbLinesValueError` if the provided value is not a
96
+ # Will raise `ArgumentError` if the provided value is not a
86
97
  # number:
87
98
  #
88
99
  # kubetailrb some-pod --tail some-string
@@ -92,11 +103,11 @@ module Kubetailrb
92
103
 
93
104
  index = args.find_index { |arg| arg == TAIL_FLAG }.to_i
94
105
 
95
- raise MissingNbLinesValueError, "Missing #{TAIL_FLAG} value." if args[index + 1].nil?
106
+ raise ArgumentError, "Missing #{TAIL_FLAG} value." if args[index + 1].nil?
96
107
 
97
108
  last_nb_lines = args[index + 1].to_i
98
109
 
99
- raise InvalidNbLinesValueError, "Invalid #{TAIL_FLAG} value: #{args[index + 1]}." if last_nb_lines.zero?
110
+ raise ArgumentError, "Invalid #{TAIL_FLAG} value: #{args[index + 1]}." if last_nb_lines.zero?
100
111
 
101
112
  last_nb_lines
102
113
  end
@@ -109,19 +120,62 @@ module Kubetailrb
109
120
  args.any? { |arg| RAW_FLAGS.include?(arg) }
110
121
  end
111
122
 
112
- def parse_pretty_print(*args)
113
- args.any? { |arg| PRETTY_PRINT_FLAGS.include?(arg) }
123
+ def parse_container_query(*args)
124
+ return DEFAULT_CONTAINER_QUERY unless args.any? { |arg| CONTAINER_FLAGS.include?(arg) }
125
+
126
+ index = args.find_index { |arg| CONTAINER_FLAGS.include?(arg) }.to_i
127
+
128
+ raise ArgumentError, "Missing #{CONTAINER_FLAGS} value." if args[index + 1].nil?
129
+
130
+ args[index + 1]
114
131
  end
115
- end
116
- end
117
132
 
118
- class MissingNbLinesValueError < RuntimeError
119
- end
133
+ def parse_display_names(*args)
134
+ args.include?(DISPLAY_NAMES_FLAG)
135
+ end
120
136
 
121
- class MissingNamespaceValueError < RuntimeError
122
- end
137
+ #
138
+ # Parse log exclusion from arguments provided in the CLI, e.g.
139
+ #
140
+ # kubetailrb some-pod --exclude access-logs,dd-logs
141
+ #
142
+ # will return [access-logs, dd-logs].
143
+ #
144
+ # Will raise `ArgumentError` if the value is not provided:
145
+ #
146
+ # kubetailrb some-pod --exclude
147
+ #
148
+ def parse_excludes(*args)
149
+ return [] unless args.any? { |arg| EXCLUDES_FLAGS.include?(arg) }
150
+
151
+ index = args.find_index { |arg| EXCLUDES_FLAGS.include?(arg) }.to_i
152
+
153
+ raise ArgumentError, "Missing #{EXCLUDES_FLAGS} value." if args[index + 1].nil?
154
+
155
+ args[index + 1].split(',')
156
+ end
157
+
158
+ #
159
+ # Parse MDCs to include from arguments provided in the CLI, e.g.
160
+ #
161
+ # kubetailrb some-pod --mdc account.id,process.thread.name
162
+ #
163
+ # will return [account.id, thread.name].
164
+ #
165
+ # Will raise `ArgumentError` if the value is not provided:
166
+ #
167
+ # kubetailrb some-pod --mdc
168
+ #
169
+ def parse_mdcs(*args)
170
+ return [] unless args.any? { |arg| MDCS_FLAGS.include?(arg) }
123
171
 
124
- class InvalidNbLinesValueError < RuntimeError
172
+ index = args.find_index { |arg| MDCS_FLAGS.include?(arg) }.to_i
173
+
174
+ raise ArgumentError, "Missing #{MDCS_FLAGS} value." if args[index + 1].nil?
175
+
176
+ args[index + 1].split(',')
177
+ end
178
+ end
125
179
  end
126
180
  end
127
181
  end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kubetailrb/validated'
4
+
5
+ module Kubetailrb
6
+ module Filter
7
+ # Filter the logs that we do not want to see.
8
+ # Currently only supporting excluding access logs and datadog logs.
9
+ class LogFilter
10
+ include Validated
11
+
12
+ def self.create(exclude)
13
+ new(exclude.include?('access-logs'), exclude.include?('dd-logs'))
14
+ end
15
+
16
+ def initialize(exclude_access_logs, exclude_dd_logs)
17
+ @exclude_access_logs = exclude_access_logs
18
+ @exclude_dd_logs = exclude_dd_logs
19
+
20
+ validate
21
+ end
22
+
23
+ # Returns true if the log should be print, false otherwise.
24
+ def test(log)
25
+ return false if @exclude_access_logs && access_log?(log)
26
+ return false if @exclude_dd_logs && dd_log?(log)
27
+
28
+ true
29
+ end
30
+
31
+ def exclude_access_logs?
32
+ @exclude_access_logs
33
+ end
34
+
35
+ def exclude_dd_logs?
36
+ @exclude_dd_logs
37
+ end
38
+
39
+ private
40
+
41
+ def validate
42
+ validate_boolean @exclude_access_logs, "Invalid exclude_access_logs: #{@exclude_access_logs}."
43
+ validate_boolean @exclude_dd_logs, "Invalid exclude_dd_logs: #{@exclude_dd_logs}."
44
+ end
45
+
46
+ def access_log?(log)
47
+ json = JSON.parse(log)
48
+ # NOTE: Shall I mutualize this function, as it's also used in
49
+ # JsonFormatter? It's only implemented in 2 places... Maybe I shall wait
50
+ # until there's a third one before applying DRY.
51
+ json.include?('http.response.status_code') || json.include?('http_status')
52
+ rescue JSON::ParserError
53
+ false
54
+ end
55
+
56
+ def dd_log?(log)
57
+ # NOTE: Is there's a better way to detect if it's a datadog log?
58
+ log.include?('[dd') || log.include?('[datadog]')
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kubetailrb/painter'
4
+ require 'kubetailrb/validated'
5
+
6
+ module Kubetailrb
7
+ module Formatter
8
+ # Format JSON to human readable.
9
+ class JsonFormatter
10
+ include Painter
11
+ include Validated
12
+
13
+ def initialize(mdcs = [])
14
+ @mdcs = mdcs
15
+
16
+ validate
17
+ end
18
+
19
+ def format(log)
20
+ json = JSON.parse(log)
21
+
22
+ return format_access_log(json) if access_log?(json)
23
+
24
+ format_application_log(json)
25
+ rescue JSON::ParserError
26
+ log
27
+ end
28
+
29
+ private
30
+
31
+ def validate
32
+ raise_if_nil @mdcs, 'MDCs not set.'
33
+ end
34
+
35
+ def access_log?(json)
36
+ json.include?('http.response.status_code') || json.include?('http_status')
37
+ end
38
+
39
+ def format_access_log(json)
40
+ "#{json["@timestamp"]}#{format_http_status_code json}#{http_method json} #{url_path json}"
41
+ end
42
+
43
+ def format_application_log(json)
44
+ "#{json["@timestamp"]}#{format_log_level json}#{format_mdcs json}#{json["message"]}#{format_stack_trace json}"
45
+ end
46
+
47
+ def format_stack_trace(json)
48
+ stack_trace = json['error.stack_trace']
49
+
50
+ return '' if stack_trace.nil? || stack_trace.strip&.empty?
51
+
52
+ "\n#{stack_trace}"
53
+ end
54
+
55
+ def format_http_status_code(json)
56
+ code = json['http.response.status_code'] || json['http_status']
57
+
58
+ return " #{highlight_blue(" I ")} [#{code}] " if code >= 200 && code < 400
59
+ return " #{highlight_yellow(" W ")} [#{code}] " if code >= 400 && code < 500
60
+ return " #{highlight_red(" E ")} [#{code}] " if code >= 500
61
+
62
+ " #{code} "
63
+ end
64
+
65
+ def format_log_level(json)
66
+ level = json['log.level'] || json.dig('log', 'level')
67
+ return ' ' if level.nil? || level.strip.empty?
68
+ return " #{highlight_blue(" I ")} " if level == 'INFO'
69
+ return " #{highlight_yellow(" W ")} " if level == 'WARN'
70
+ return " #{highlight_red(" E ")} " if level == 'ERROR'
71
+
72
+ " #{level} "
73
+ end
74
+
75
+ def http_method(json)
76
+ json['http.request.method'] || json['http_method']
77
+ end
78
+
79
+ def url_path(json)
80
+ json['url.path'] || json['http_path']
81
+ end
82
+
83
+ def format_mdcs(json)
84
+ result = ''
85
+ @mdcs.each do |mdc|
86
+ value = json[mdc] || json.dig(*mdc.split('.'))
87
+ result += "#{cyan("#{mdc}=#{value}")} " unless value.nil?
88
+ end
89
+ result.to_s
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kubetailrb
4
+ module Formatter
5
+ # Formatter that does nothing except return what's given to it.
6
+ class NoOpFormatter
7
+ def format(log)
8
+ log
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kubetailrb/validated'
4
+
5
+ module Kubetailrb
6
+ module Formatter
7
+ # Display the pod and container name.
8
+ class PodMetadataFormatter
9
+ include Validated
10
+
11
+ def initialize(pod_name, container_name, formatter)
12
+ @pod_name = pod_name
13
+ @container_name = container_name
14
+ @formatter = formatter
15
+
16
+ validate
17
+ end
18
+
19
+ def format(log)
20
+ "#{@pod_name}/#{@container_name} | #{@formatter.format(log)}"
21
+ end
22
+
23
+ private
24
+
25
+ def validate
26
+ raise_if_blank @pod_name, 'Pod name not set.'
27
+ raise_if_blank @container_name, 'Container name not set.'
28
+ raise_if_nil @formatter, 'Formatter not set.'
29
+ end
30
+ end
31
+ end
32
+ end
@@ -7,13 +7,27 @@ module Kubetailrb
7
7
  class K8sOpts
8
8
  include Validated
9
9
 
10
- attr_reader :namespace, :last_nb_lines
11
-
12
- def initialize(namespace:, last_nb_lines:, follow:, raw:)
10
+ DEFAULT_NAMESPACE = 'default'
11
+ DEFAULT_NB_LINES = 10
12
+
13
+ attr_reader :namespace, :last_nb_lines, :excludes, :mdcs
14
+
15
+ def initialize( # rubocop:disable Metrics/ParameterLists
16
+ namespace: DEFAULT_NAMESPACE,
17
+ last_nb_lines: DEFAULT_NB_LINES,
18
+ follow: false,
19
+ raw: false,
20
+ display_names: false,
21
+ excludes: [],
22
+ mdcs: []
23
+ )
13
24
  @namespace = namespace
14
25
  @last_nb_lines = last_nb_lines
15
26
  @follow = follow
16
27
  @raw = raw
28
+ @display_names = display_names
29
+ @excludes = excludes
30
+ @mdcs = mdcs
17
31
 
18
32
  validate
19
33
  end
@@ -26,6 +40,10 @@ module Kubetailrb
26
40
  @raw
27
41
  end
28
42
 
43
+ def display_names?
44
+ @display_names
45
+ end
46
+
29
47
  private
30
48
 
31
49
  def validate
@@ -33,6 +51,9 @@ module Kubetailrb
33
51
  validate_last_nb_lines @last_nb_lines
34
52
  validate_boolean @follow, "Invalid follow: #{@follow}."
35
53
  validate_boolean @raw, "Invalid raw: #{@raw}."
54
+ validate_boolean @display_names, "Invalid display names: #{@display_names}."
55
+ raise_if_nil @excludes, 'Excludes not set.'
56
+ raise_if_nil @mdcs, 'MDCs not set.'
36
57
  end
37
58
  end
38
59
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kubetailrb
4
+ # Add behaviors to colorize console output.
5
+ module Painter
6
+ def blue(text)
7
+ colorize(text, '34')
8
+ end
9
+
10
+ def red(text)
11
+ colorize(text, '31')
12
+ end
13
+
14
+ def cyan(text)
15
+ colorize(text, '36')
16
+ end
17
+
18
+ def highlight_blue(text)
19
+ colorize(text, '1;30;44')
20
+ end
21
+
22
+ def highlight_yellow(text)
23
+ colorize(text, '1;30;43')
24
+ end
25
+
26
+ def highlight_red(text)
27
+ colorize(text, '1;30;41')
28
+ end
29
+
30
+ private
31
+
32
+ def colorize(text, color_code)
33
+ "\e[#{color_code}m#{text}\e[0m"
34
+ end
35
+ end
36
+ end