From fbe78d0c9341f548cea7fcf6f0515196f55a700d Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Mon, 21 Mar 2022 16:50:14 +0530 Subject: [PATCH 01/13] CFINSPEC-86: Enhance docker_image with image inspect information Signed-off-by: Sonu Saha --- lib/inspec/resources/docker_image.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/inspec/resources/docker_image.rb b/lib/inspec/resources/docker_image.rb index 496ca504c..0353c1fb0 100644 --- a/lib/inspec/resources/docker_image.rb +++ b/lib/inspec/resources/docker_image.rb @@ -48,6 +48,23 @@ module Inspec::Resources object_info.tags[0] if object_info.entries.size == 1 end + def [](hashkeys) + hash_value = image_inspect_info + keys = hashkeys.split(".") + keys.each do |k| + if hash_value.include?(k.to_sym) + hash_value = hash_value[k.to_sym] + else + raise Inspec::Exceptions::ResourceFailed, "#{hashkeys} is not a valid key for your image, #{k} not found." + end + end + hash_value + end + + def inspection + image_inspect_info + end + def to_s img = @opts[:image] || @opts[:id] "Docker Image #{img}" @@ -80,5 +97,11 @@ module Inspec::Resources (repository == opts[:repo] && tag == opts[:tag]) || (!id.nil? && !opts[:id].nil? && (id == opts[:id] || id.start_with?(opts[:id]))) end end + + def image_inspect_info + return @inspect_info if defined?(@inspect_info) + + @inspect_info = inspec.docker.object(@opts[:image] || (!opts[:id].nil? && @opts[:id])) + end end end From 2c4b8bab40926ac5c5e5e59a4a9911df1dd11eef Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Tue, 22 Mar 2022 14:07:28 +0530 Subject: [PATCH 02/13] CFINSPEC-86: Add unit test for docker_image inspect attributes Signed-off-by: Sonu Saha --- test/fixtures/cmd/docker-inspect-image | 88 ++++++++++++++++++++++++ test/helpers/mock_loader.rb | 1 + test/unit/resources/docker_image_test.rb | 9 +++ 3 files changed, 98 insertions(+) create mode 100644 test/fixtures/cmd/docker-inspect-image diff --git a/test/fixtures/cmd/docker-inspect-image b/test/fixtures/cmd/docker-inspect-image new file mode 100644 index 000000000..3970a0352 --- /dev/null +++ b/test/fixtures/cmd/docker-inspect-image @@ -0,0 +1,88 @@ +[ + { + "Id": "sha256:a457a74c9aaabc62ddc119d2fb03ba6f58fa299bf766bd2411c159142b972c1d", + "RepoTags": [ + "ubuntu:latest" + ], + "RepoDigests": [ + "ubuntu@sha256:669e010b58baf5beb2836b253c1fd5768333f0d1dbcb834f7c07a4dc93f474be" + ], + "Parent": "", + "Comment": "", + "Created": "2022-02-02T03:19:27.692029463Z", + "Container": "396e646862a702db784450345079c41dc9da7103da54ca3d777394b06aba775e", + "ContainerConfig": { + "Hostname": "396e646862a7", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ", + "CMD [\"bash\"]" + ], + "Image": "sha256:90d6079446c1908361700f819e620a87b923908fe4a1c5bfb12ae45b36358547", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": {} + }, + "DockerVersion": "20.10.7", + "Author": "", + "Config": { + "Hostname": "", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "bash" + ], + "Image": "sha256:90d6079446c1908361700f819e620a87b923908fe4a1c5bfb12ae45b36358547", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": null + }, + "Architecture": "arm64", + "Variant": "v8", + "Os": "linux", + "Size": 65592278, + "VirtualSize": 65592278, + "GraphDriver": { + "Data": { + "MergedDir": "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged", + "UpperDir": "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/diff", + "WorkDir": "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/work" + }, + "Name": "overlay2" + }, + "RootFS": { + "Type": "layers", + "Layers": [ + "sha256:0c20a4bc193b305ce66d3bde10d177631646a8844804953c320f1f5b68655213" + ] + }, + "Metadata": { + "LastTagTime": "0001-01-01T00:00:00Z" + } + } +] diff --git a/test/helpers/mock_loader.rb b/test/helpers/mock_loader.rb index 07fdf9369..e7ba99346 100644 --- a/test/helpers/mock_loader.rb +++ b/test/helpers/mock_loader.rb @@ -473,6 +473,7 @@ class MockLoader "docker inspect 71b5df59442b" => cmd.call("docker-inspec"), # docker images "83c36bfade9375ae1feb91023cd1f7409b786fd992ad4013bf0f2259d33d6406" => cmd.call("docker-images"), + "docker inspect ubuntu:latest" => cmd.call("docker-inspect-image"), # docker services %{docker service ls --format '{"ID": {{json .ID}}, "Name": {{json .Name}}, "Mode": {{json .Mode}}, "Replicas": {{json .Replicas}}, "Image": {{json .Image}}, "Ports": {{json .Ports}}}'} => cmd.call("docker-service-ls"), # docker plugins diff --git a/test/unit/resources/docker_image_test.rb b/test/unit/resources/docker_image_test.rb index 04155af51..82db0f528 100644 --- a/test/unit/resources/docker_image_test.rb +++ b/test/unit/resources/docker_image_test.rb @@ -12,6 +12,15 @@ describe "Inspec::Resources::DockerImage" do _(resource.repo).must_equal "alpine" end + it "check attributes returned by docker inspect [docker_image]" do + resource = load_resource("docker_image", "ubuntu:latest") + _(resource["Architecture"]).must_equal "arm64" + _(resource["Config.Cmd"]).must_include "bash" + # Check, minitest equivalent for: 'Architecture' => 'arm64 + _(resource::inspection).must_include 'Architecture' + _(resource::inspection.Architecture).must_equal 'arm64' + end + it "prints as a docker_image resource" do resource = load_resource("docker_image", "alpine") _(resource.to_s).must_equal "Docker Image alpine:latest" From 968537da1e70d77d69c72dd32b0c66a90307635b Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Tue, 22 Mar 2022 15:27:33 +0530 Subject: [PATCH 03/13] CFINSPEC-86: Correct RuboCop Lint offenses Signed-off-by: Sonu Saha --- test/unit/resources/docker_image_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/resources/docker_image_test.rb b/test/unit/resources/docker_image_test.rb index 82db0f528..0a0b70c7a 100644 --- a/test/unit/resources/docker_image_test.rb +++ b/test/unit/resources/docker_image_test.rb @@ -17,8 +17,8 @@ describe "Inspec::Resources::DockerImage" do _(resource["Architecture"]).must_equal "arm64" _(resource["Config.Cmd"]).must_include "bash" # Check, minitest equivalent for: 'Architecture' => 'arm64 - _(resource::inspection).must_include 'Architecture' - _(resource::inspection.Architecture).must_equal 'arm64' + _(resource.inspection).must_include "Architecture" + _(resource.inspection.Architecture).must_equal "arm64" end it "prints as a docker_image resource" do From 3b49b967a41b1a2ff08dced22204ad9f93ef56c4 Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Tue, 22 Mar 2022 16:11:10 +0530 Subject: [PATCH 04/13] CFINSPEC-86: Extend docker_image documentation with new properties Signed-off-by: Sonu Saha --- .../content/inspec/resources/docker_image.md | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/docs-chef-io/content/inspec/resources/docker_image.md b/docs-chef-io/content/inspec/resources/docker_image.md index 3487644c1..aff51fec4 100644 --- a/docs-chef-io/content/inspec/resources/docker_image.md +++ b/docs-chef-io/content/inspec/resources/docker_image.md @@ -54,7 +54,7 @@ You can also pass in repository and tag as separate values ... end -## Property Examples +## Properties ### id @@ -80,15 +80,22 @@ The `tag` property tests the value of image tag: its('tag') { should eq 'latest' } -### Test a Docker Image +### Low-level information of docker image as `docker_image`'s Property +`:inspection` property allows testing the low-level information of docker image returned by `docker inspect [docker_image]`. Use hash format `'key' => 'value` for testing the information. + + its(:inspection) { should include "Key" => "Value" } + its(:inspection) { should include "Key" => + { + "SubKey" => "Value1", + "SubKey" => "Value2" + } + } + +Additionally, all keys of the low-level information are valid properties and can be passed in square brackets when writing the test. + + its([key]) { should eq some_value } + its([key1.key2]) { should include some_value } - describe docker_image('alpine:latest') do - it { should exist } - its('id') { should eq 'sha256:4a415e...a526' } - its('image') { should eq 'alpine:latest' } - its('repo') { should eq 'alpine' } - its('tag') { should eq 'latest' } - end ## Matchers @@ -99,3 +106,35 @@ For a full list of available matchers, please visit our [matchers page](/inspec/ The `exist` matcher tests if the image is available on the node: it { should exist } + +## Examples +### Test if a docker image exists and verify the image properties: `id`, `image`, `repo` and `tag`. + + describe docker_image('alpine:latest') do + it { should exist } + its('id') { should eq 'sha256:4a415e...a526' } + its('image') { should eq 'alpine:latest' } + its('repo') { should eq 'alpine' } + its('tag') { should eq 'latest' } + end + +### Test if a docker image exists and verify the low level information: `Architecture`, `Config.Cmd`, `Os`, and `GraphDriver` + + describe docker_image('ubuntu:latest') do + it { should exist } + its(['Architecture']) { should eq 'arm64' } + its(['Config.Cmd']) { should include 'bash' } + its(['GraphDriver.Data.MergedDir']) { should include "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged" } + its(:inspection) { should include 'Architecture' => 'arm64' } + its(:inspection) { should_not include 'Architecture' => 'i386' } + its(:inspection) { should include "GraphDriver" => + { + "Data" => { + "MergedDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged", + "UpperDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/diff", + "WorkDir"=> "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/work" + }, + "Name" => "overlay2" + } + } + end \ No newline at end of file From d66fcd039aaba924dd057a819eaf66505ab54396 Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Wed, 23 Mar 2022 23:21:22 +0530 Subject: [PATCH 05/13] CFINSPEC-86: Allow container id to test inspect attributes Signed-off-by: Sonu Saha --- lib/inspec/resources/docker_image.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/inspec/resources/docker_image.rb b/lib/inspec/resources/docker_image.rb index 0353c1fb0..0422b7857 100644 --- a/lib/inspec/resources/docker_image.rb +++ b/lib/inspec/resources/docker_image.rb @@ -101,7 +101,7 @@ module Inspec::Resources def image_inspect_info return @inspect_info if defined?(@inspect_info) - @inspect_info = inspec.docker.object(@opts[:image] || (!opts[:id].nil? && @opts[:id])) + @inspect_info = inspec.docker.object(@opts[:image] || (!@opts[:id].nil? && @opts[:id])) end end end From bfb78a2d23f2d1845fc0824c9da7c6334c07f159 Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Thu, 24 Mar 2022 12:25:36 +0530 Subject: [PATCH 06/13] CFINSPEC-86: Factorize def[] method Signed-off-by: Sonu Saha --- lib/inspec/resources/docker_image.rb | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/inspec/resources/docker_image.rb b/lib/inspec/resources/docker_image.rb index 0422b7857..0357f4ebe 100644 --- a/lib/inspec/resources/docker_image.rb +++ b/lib/inspec/resources/docker_image.rb @@ -49,16 +49,10 @@ module Inspec::Resources end def [](hashkeys) - hash_value = image_inspect_info - keys = hashkeys.split(".") - keys.each do |k| - if hash_value.include?(k.to_sym) - hash_value = hash_value[k.to_sym] - else - raise Inspec::Exceptions::ResourceFailed, "#{hashkeys} is not a valid key for your image, #{k} not found." - end - end - hash_value + hashkeys = hashkeys.split(".").map(&:to_sym) + image_inspect_info.dig(*hashkeys) + rescue + raise Inspec::Exceptions::ResourceFailed, "#{hashkeys.join(".")} is not a valid key for your image" end def inspection From 9a9a5acb7a77e3b7cfab183d85abd30c368c6284 Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Thu, 24 Mar 2022 15:31:58 +0530 Subject: [PATCH 07/13] CFINSPEC-86: Replace def[] and override method_missing of json resource Signed-off-by: Sonu Saha --- lib/inspec/resources/docker_image.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/inspec/resources/docker_image.rb b/lib/inspec/resources/docker_image.rb index 0357f4ebe..6e4248b88 100644 --- a/lib/inspec/resources/docker_image.rb +++ b/lib/inspec/resources/docker_image.rb @@ -2,10 +2,11 @@ # Copyright 2017, Christoph Hartmann require "inspec/resources/docker" +require "inspec/resources/json" require_relative "docker_object" module Inspec::Resources - class DockerImage < Inspec.resource(1) + class DockerImage < JsonConfig include Inspec::Resources::DockerObject name "docker_image" @@ -34,6 +35,7 @@ module Inspec::Resources o = opts.dup o = { image: opts } if opts.is_a?(String) @opts = sanitize_options(o) + super({ content: image_inspect_info.to_json }) end def image @@ -48,11 +50,12 @@ module Inspec::Resources object_info.tags[0] if object_info.entries.size == 1 end - def [](hashkeys) - hashkeys = hashkeys.split(".").map(&:to_sym) - image_inspect_info.dig(*hashkeys) - rescue - raise Inspec::Exceptions::ResourceFailed, "#{hashkeys.join(".")} is not a valid key for your image" + def method_missing(*keys) + keys.shift if keys.is_a?(Array) && keys[0] == :[] + inspect_value = value(keys.map { |key| key.split(".") }.flatten) + raise Inspec::Exceptions::ResourceFailed, "#{keys.join(".")} is not a valid key for your image" if inspect_value.nil? + + inspect_value end def inspection From 3eba207bcf87c0862fbbc4d83b1981113226bbf7 Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Thu, 24 Mar 2022 22:05:59 +0530 Subject: [PATCH 08/13] CFINSPEC-86: Use method_missing and dig to achieve the goal Signed-off-by: Sonu Saha --- lib/inspec/resources/docker_image.rb | 48 +++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/lib/inspec/resources/docker_image.rb b/lib/inspec/resources/docker_image.rb index 6e4248b88..285d0ae0d 100644 --- a/lib/inspec/resources/docker_image.rb +++ b/lib/inspec/resources/docker_image.rb @@ -2,11 +2,10 @@ # Copyright 2017, Christoph Hartmann require "inspec/resources/docker" -require "inspec/resources/json" require_relative "docker_object" module Inspec::Resources - class DockerImage < JsonConfig + class DockerImage < Inspec.resource(1) include Inspec::Resources::DockerObject name "docker_image" @@ -35,7 +34,6 @@ module Inspec::Resources o = opts.dup o = { image: opts } if opts.is_a?(String) @opts = sanitize_options(o) - super({ content: image_inspect_info.to_json }) end def image @@ -50,12 +48,18 @@ module Inspec::Resources object_info.tags[0] if object_info.entries.size == 1 end - def method_missing(*keys) - keys.shift if keys.is_a?(Array) && keys[0] == :[] - inspect_value = value(keys.map { |key| key.split(".") }.flatten) - raise Inspec::Exceptions::ResourceFailed, "#{keys.join(".")} is not a valid key for your image" if inspect_value.nil? + # method_missing handles when hash_keys are invoked to check information obtained on docker inspect [image_name] + def method_missing(*hash_keys) + # User can test the low-level inspect information in three ways: + # Way 1: Serverspec style: its(['Config.Cmd']) { should include some_value } + # here, the value for hash_keys recieved is [:[], "Config.Cmd"] + # Way 2: InSpec style: its(['Config','Cmd']) { should include some_value } + # here, the value for hash_keys recieved is [:[], "Config", "Cmd"] + # Way 3: Mix of both: its(['GraphDriver.Data','MergedDir']) { should include some_value } + # here, the value for hash_keys recieved is [:[], "GraphDriver.Data", "MergedDir"] - inspect_value + # hash_keys are passed to this method to evaluate the value + image_hash_inspection(hash_keys) end def inspection @@ -95,10 +99,38 @@ module Inspec::Resources end end + # image_inspect_info returns the complete inspect hash_values of the image def image_inspect_info return @inspect_info if defined?(@inspect_info) @inspect_info = inspec.docker.object(@opts[:image] || (!@opts[:id].nil? && @opts[:id])) end + + # image_hash_inspection formats the input hash_keys and checks if any value exists for such keys in @inspect_info(image_inspect_info) + def image_hash_inspection(hash_keys) + # The hash_keys recieved are in three formats as mentioned in method_missing + # The hash_keys recieved must be in array format [] and the zeroth index must be :[] + # Check for the conditions and remove the zeroth element from the hash_keys + + hash_keys.shift if hash_keys.is_a?(Array) && hash_keys[0] == :[] + + # When received hash_keys in Serverspec style or mix of both + # The hash_keys are to be splitted at '.' (dot) and flatten it so that it doesn't become array of arrays + # After splitting and flattening is done, hash_keys is now an array with individual keys + hash_keys = hash_keys.map { |key| key.split(".") }.flatten + + # image_inspect_info returns the complete inspect hash_values of the image + # dig() finds the nested value specified by the sequence of the key object by calling dig at each step. + # hash_keys is the key object. If one of the key is bad, value will be nil. + hash_value = image_inspect_info.dig(*hash_keys) + + # If one of the key is bad, hash_value will be nil, so raise exception which throws it in rescue block + # else return hash_value + raise Inspec::Exceptions::ResourceFailed if hash_value.nil? + + hash_value + rescue + raise Inspec::Exceptions::ResourceFailed, "#{hash_keys.join(".")} is not a valid key for your image or has nil value." + end end end From f6115c7aeb1ea26a8752df7871c44d2eeb54ce97 Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Thu, 24 Mar 2022 22:49:01 +0530 Subject: [PATCH 09/13] CFINSPEC-86: Add comments and unit test for invalid keys Signed-off-by: Sonu Saha --- lib/inspec/resources/docker_image.rb | 1 + test/unit/resources/docker_image_test.rb | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/inspec/resources/docker_image.rb b/lib/inspec/resources/docker_image.rb index 285d0ae0d..0d24eff72 100644 --- a/lib/inspec/resources/docker_image.rb +++ b/lib/inspec/resources/docker_image.rb @@ -62,6 +62,7 @@ module Inspec::Resources image_hash_inspection(hash_keys) end + # inspection property allows to test any of the hash key-value pairs as part of the image_inspect_info def inspection image_inspect_info end diff --git a/test/unit/resources/docker_image_test.rb b/test/unit/resources/docker_image_test.rb index 0a0b70c7a..e44b9ae11 100644 --- a/test/unit/resources/docker_image_test.rb +++ b/test/unit/resources/docker_image_test.rb @@ -12,15 +12,22 @@ describe "Inspec::Resources::DockerImage" do _(resource.repo).must_equal "alpine" end + # Test case for inspect image information handled by inspection and method_missing it "check attributes returned by docker inspect [docker_image]" do resource = load_resource("docker_image", "ubuntu:latest") _(resource["Architecture"]).must_equal "arm64" _(resource["Config.Cmd"]).must_include "bash" - # Check, minitest equivalent for: 'Architecture' => 'arm64 _(resource.inspection).must_include "Architecture" _(resource.inspection.Architecture).must_equal "arm64" end + # Test case for inspect image information with invalid keys + it "checks exception when key is invalid or doesn't exist as part of the inspect information" do + resource = load_resource("docker_image", "ubuntu:latest") + ex = _ { resource["Garbage.Key"] }.must_raise(Inspec::Exceptions::ResourceFailed) + _(ex.message).must_include "Garbage.Key is not a valid key for your image or has nil value." + end + it "prints as a docker_image resource" do resource = load_resource("docker_image", "alpine") _(resource.to_s).must_equal "Docker Image alpine:latest" From 504756c8d1b1f1966cf420550a97756e81eae1d6 Mon Sep 17 00:00:00 2001 From: Sonu Saha Date: Thu, 24 Mar 2022 23:02:55 +0530 Subject: [PATCH 10/13] CFINSPEC-86: Add syntax in documentation Signed-off-by: Sonu Saha --- .../content/inspec/resources/docker_image.md | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/docs-chef-io/content/inspec/resources/docker_image.md b/docs-chef-io/content/inspec/resources/docker_image.md index aff51fec4..56db34ddf 100644 --- a/docs-chef-io/content/inspec/resources/docker_image.md +++ b/docs-chef-io/content/inspec/resources/docker_image.md @@ -81,6 +81,8 @@ The `tag` property tests the value of image tag: its('tag') { should eq 'latest' } ### Low-level information of docker image as `docker_image`'s Property + +#### inspection `:inspection` property allows testing the low-level information of docker image returned by `docker inspect [docker_image]`. Use hash format `'key' => 'value` for testing the information. its(:inspection) { should include "Key" => "Value" } @@ -91,11 +93,21 @@ The `tag` property tests the value of image tag: } } -Additionally, all keys of the low-level information are valid properties and can be passed in square brackets when writing the test. - - its([key]) { should eq some_value } - its([key1.key2]) { should include some_value } - +#### Additionally, all keys of the low-level information are valid properties and can be passed in three ways when writing the test. +- Serverspec's syntax +``` + its(['key']) { should eq some_value } + its(['key1.key2.key3']) { should include some_value } +``` +- InSpec's syntax +``` + its(['key']) { should eq some_value } + its(['key1', 'key2', 'key3']) { should include some_value } +``` +- Combination of Serverspec and InSpec +``` + its(['key1.key2', 'key3']) { should include some_value } +``` ## Matchers From d1bf94daaf9ff7b138a6c22347ee08053dfdfa1a Mon Sep 17 00:00:00 2001 From: Deepa Kumaraswamy Date: Tue, 29 Mar 2022 16:32:53 +0530 Subject: [PATCH 11/13] review changes Signed-off-by: Deepa Kumaraswamy --- .../content/inspec/resources/docker_image.md | 153 +++++++++--------- 1 file changed, 78 insertions(+), 75 deletions(-) diff --git a/docs-chef-io/content/inspec/resources/docker_image.md b/docs-chef-io/content/inspec/resources/docker_image.md index 56db34ddf..ce3391d2b 100644 --- a/docs-chef-io/content/inspec/resources/docker_image.md +++ b/docs-chef-io/content/inspec/resources/docker_image.md @@ -11,103 +11,105 @@ platform = "linux" parent = "inspec/resources/os" +++ -Use the `docker_image` Chef InSpec audit resource to verify a Docker image. +Use the `docker_image` Chef InSpec audit resource to verify a Docker image. A Docker Image is a template that contains the application and all the dependencies required to run an application on Docker. ## Availability ### Installation -This resource is distributed along with Chef InSpec itself. You can use it automatically. +This resource is distributed with Chef InSpec. ### Version -This resource first became available in v1.21.0 of InSpec. +This resource is available from the InSpec version, 1.21.0. ## Syntax -A `docker_image` resource block declares the image: +A `docker_image` resource block declares the image. - describe docker_image('alpine:latest') do - it { should exist } - its('id') { should eq 'sha256:4a415e...a526' } - its('repo') { should eq 'alpine' } - its('tag') { should eq 'latest' } - end + describe docker_image('ALPINE:LATEST') do + it { should exist } + its('id') { should eq 'sha256:4a415e...a526' } + its('repo') { should eq 'ALPINE' } + its('tag') { should eq 'LATEST' } + end -## Resource Parameter Examples +### Resource Parameter Examples -The resource allows you to pass in an image id: +The resource allows you to pass with an image ID. - describe docker_image(id: alpine_id) do + describe docker_image(id: ID) do + ... + end + +If the tag is missing for an image, `LATEST` is assumed as default. + + describe docker_image('ALPINE') do ... end -If the tag is missing for an image, `latest` is assumed as default: +You can also pass the repository and tag values as separate values. - describe docker_image('alpine') do - ... - end - -You can also pass in repository and tag as separate values - - describe docker_image(repo: 'alpine', tag: 'latest') do - ... - end + describe docker_image(repo: 'ALPINE', tag: 'LATEST') do + ... + end ## Properties ### id -The `id` property returns the full image id: +The `id` property returns the full image ID. - its('id') { should eq 'sha256:4a415e3663882fbc554ee830889c68a33b3585503892cc718a4698e91ef2a526' } + its('id') { should eq 'sha256:4a415e3663882fbc554ee830889c68a33b3585503892cc718a4698e91ef2a526' } ### image -The `image` property tests the value of the image. It is a combination of `repository/tag`: +The `image` property tests the value of the image. It is a combination of `repository/tag`. - its('image') { should eq 'alpine:latest' } + its('image') { should eq 'ALPINE:LATEST' } ### repo -The `repo` property tests the value of the repository name: +The `repo` property tests the value of the repository name. - its('repo') { should eq 'alpine' } + its('repo') { should eq 'ALPINE' } ### tag -The `tag` property tests the value of image tag: +The `tag` property tests the value of the image tag. - its('tag') { should eq 'latest' } + its('tag') { should eq 'LATEST' } -### Low-level information of docker image as `docker_image`'s Property +### Low-level information of docker image as docker_image's property -#### inspection -`:inspection` property allows testing the low-level information of docker image returned by `docker inspect [docker_image]`. Use hash format `'key' => 'value` for testing the information. +#### Inspection - its(:inspection) { should include "Key" => "Value" } - its(:inspection) { should include "Key" => - { - "SubKey" => "Value1", - "SubKey" => "Value2" - } +:inspection + The property allows testing the low-level information of docker image returned by `docker inspect [docker_image]`. Use hash format `'key' => 'value` for testing the information. + + its(:inspection) { should include "Key" => "Value" } + its(:inspection) { should include "Key" => + { + "SubKey" => "Value1", + "SubKey" => "Value2" } + } + +Additionally, all keys of the low-level information are valid properties and can be passed in three ways when writing the test. -#### Additionally, all keys of the low-level information are valid properties and can be passed in three ways when writing the test. - Serverspec's syntax -``` + its(['key']) { should eq some_value } its(['key1.key2.key3']) { should include some_value } -``` + - InSpec's syntax -``` + its(['key']) { should eq some_value } its(['key1', 'key2', 'key3']) { should include some_value } -``` + - Combination of Serverspec and InSpec -``` + its(['key1.key2', 'key3']) { should include some_value } -``` ## Matchers @@ -115,38 +117,39 @@ For a full list of available matchers, please visit our [matchers page](/inspec/ ### exist -The `exist` matcher tests if the image is available on the node: +The `exist` matcher tests if the image is available on the node. - it { should exist } + it { should exist } ## Examples -### Test if a docker image exists and verify the image properties: `id`, `image`, `repo` and `tag`. - describe docker_image('alpine:latest') do - it { should exist } - its('id') { should eq 'sha256:4a415e...a526' } - its('image') { should eq 'alpine:latest' } - its('repo') { should eq 'alpine' } - its('tag') { should eq 'latest' } - end +### Test if a docker image exists and verifies the image properties: ID, image, repository, and tag -### Test if a docker image exists and verify the low level information: `Architecture`, `Config.Cmd`, `Os`, and `GraphDriver` + describe docker_image('ALPINE:LATEST') do + it { should exist } + its('id') { should eq 'sha256:4a415e...a526' } + its('image') { should eq 'ALPINE:LATEST' } + its('repo') { should eq 'ALPINE' } + its('tag') { should eq 'LATEST' } + end - describe docker_image('ubuntu:latest') do - it { should exist } - its(['Architecture']) { should eq 'arm64' } - its(['Config.Cmd']) { should include 'bash' } - its(['GraphDriver.Data.MergedDir']) { should include "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged" } - its(:inspection) { should include 'Architecture' => 'arm64' } - its(:inspection) { should_not include 'Architecture' => 'i386' } - its(:inspection) { should include "GraphDriver" => - { - "Data" => { - "MergedDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged", - "UpperDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/diff", - "WorkDir"=> "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/work" - }, - "Name" => "overlay2" - } +### Test if a docker image exists and verifies the low-level information: Architecture, Config.Cmd, OS, and GraphDriver + + describe docker_image('ubuntu:latest') do + it { should exist } + its(['Architecture']) { should eq 'ARM64' } + its(['Config.Cmd']) { should include 'BASH' } + its(['GraphDriver.Data.MergedDir']) { should include "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged" } + its(:inspection) { should include 'Architecture' => 'ARM64' } + its(:inspection) { should_not include 'Architecture' => 'i386' } + its(:inspection) { should include "GraphDriver" => + { + "Data" => { + "MergedDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged", + "UpperDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/diff", + "WorkDir"=> "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/work" + }, + "Name" => "overlay2" } - end \ No newline at end of file + } + end From b116ad3e6bc9a21effbb0f4dbcde3aac7a3113b0 Mon Sep 17 00:00:00 2001 From: Deepa Kumaraswamy Date: Tue, 29 Mar 2022 17:18:36 +0530 Subject: [PATCH 12/13] formatting changes Signed-off-by: Deepa Kumaraswamy --- .../content/inspec/resources/docker_image.md | 105 +++++++++--------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/docs-chef-io/content/inspec/resources/docker_image.md b/docs-chef-io/content/inspec/resources/docker_image.md index ce3391d2b..933381bb1 100644 --- a/docs-chef-io/content/inspec/resources/docker_image.md +++ b/docs-chef-io/content/inspec/resources/docker_image.md @@ -27,20 +27,20 @@ This resource is available from the InSpec version, 1.21.0. A `docker_image` resource block declares the image. - describe docker_image('ALPINE:LATEST') do - it { should exist } - its('id') { should eq 'sha256:4a415e...a526' } - its('repo') { should eq 'ALPINE' } - its('tag') { should eq 'LATEST' } - end + describe docker_image('ALPINE:LATEST') do + it { should exist } + its('id') { should eq 'sha256:4a415e...a526' } + its('repo') { should eq 'ALPINE' } + its('tag') { should eq 'LATEST' } + end ### Resource Parameter Examples The resource allows you to pass with an image ID. - describe docker_image(id: ID) do - ... - end + describe docker_image(id: ID) do + ... + end If the tag is missing for an image, `LATEST` is assumed as default. @@ -50,9 +50,9 @@ If the tag is missing for an image, `LATEST` is assumed as default. You can also pass the repository and tag values as separate values. - describe docker_image(repo: 'ALPINE', tag: 'LATEST') do - ... - end + describe docker_image(repo: 'ALPINE', tag: 'LATEST') do + ... + end ## Properties @@ -60,56 +60,57 @@ You can also pass the repository and tag values as separate values. The `id` property returns the full image ID. - its('id') { should eq 'sha256:4a415e3663882fbc554ee830889c68a33b3585503892cc718a4698e91ef2a526' } + its('id') { should eq 'sha256:4a415e3663882fbc554ee830889c68a33b3585503892cc718a4698e91ef2a526' } ### image The `image` property tests the value of the image. It is a combination of `repository/tag`. - its('image') { should eq 'ALPINE:LATEST' } + its('image') { should eq 'ALPINE:LATEST' } ### repo The `repo` property tests the value of the repository name. - its('repo') { should eq 'ALPINE' } + its('repo') { should eq 'ALPINE' } ### tag The `tag` property tests the value of the image tag. - its('tag') { should eq 'LATEST' } + its('tag') { should eq 'LATEST' } ### Low-level information of docker image as docker_image's property #### Inspection :inspection + The property allows testing the low-level information of docker image returned by `docker inspect [docker_image]`. Use hash format `'key' => 'value` for testing the information. - its(:inspection) { should include "Key" => "Value" } - its(:inspection) { should include "Key" => - { - "SubKey" => "Value1", - "SubKey" => "Value2" + its(:inspection) { should include "Key" => "Value" } + its(:inspection) { should include "Key" => + { + "SubKey" => "Value1", + "SubKey" => "Value2" + } } - } Additionally, all keys of the low-level information are valid properties and can be passed in three ways when writing the test. - Serverspec's syntax - its(['key']) { should eq some_value } - its(['key1.key2.key3']) { should include some_value } + its(['key']) { should eq some_value } + its(['key1.key2.key3']) { should include some_value } - InSpec's syntax - its(['key']) { should eq some_value } - its(['key1', 'key2', 'key3']) { should include some_value } + its(['key']) { should eq some_value } + its(['key1', 'key2', 'key3']) { should include some_value } - Combination of Serverspec and InSpec - its(['key1.key2', 'key3']) { should include some_value } + its(['key1.key2', 'key3']) { should include some_value } ## Matchers @@ -119,37 +120,37 @@ For a full list of available matchers, please visit our [matchers page](/inspec/ The `exist` matcher tests if the image is available on the node. - it { should exist } + it { should exist } ## Examples ### Test if a docker image exists and verifies the image properties: ID, image, repository, and tag - describe docker_image('ALPINE:LATEST') do - it { should exist } - its('id') { should eq 'sha256:4a415e...a526' } - its('image') { should eq 'ALPINE:LATEST' } - its('repo') { should eq 'ALPINE' } - its('tag') { should eq 'LATEST' } - end + describe docker_image('ALPINE:LATEST') do + it { should exist } + its('id') { should eq 'sha256:4a415e...a526' } + its('image') { should eq 'ALPINE:LATEST' } + its('repo') { should eq 'ALPINE' } + its('tag') { should eq 'LATEST' } + end ### Test if a docker image exists and verifies the low-level information: Architecture, Config.Cmd, OS, and GraphDriver - describe docker_image('ubuntu:latest') do - it { should exist } - its(['Architecture']) { should eq 'ARM64' } - its(['Config.Cmd']) { should include 'BASH' } - its(['GraphDriver.Data.MergedDir']) { should include "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged" } - its(:inspection) { should include 'Architecture' => 'ARM64' } - its(:inspection) { should_not include 'Architecture' => 'i386' } - its(:inspection) { should include "GraphDriver" => - { - "Data" => { - "MergedDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged", - "UpperDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/diff", - "WorkDir"=> "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/work" - }, - "Name" => "overlay2" + describe docker_image('ubuntu:latest') do + it { should exist } + its(['Architecture']) { should eq 'ARM64' } + its(['Config.Cmd']) { should include 'BASH' } + its(['GraphDriver.Data.MergedDir']) { should include "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged" } + its(:inspection) { should include 'Architecture' => 'ARM64' } + its(:inspection) { should_not include 'Architecture' => 'i386' } + its(:inspection) { should include "GraphDriver" => + { + "Data" => { + "MergedDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/merged", + "UpperDir" => "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/diff", + "WorkDir"=> "/var/lib/docker/overlay2/4336ba2a87c8d82abaa9ee5afd3ac20ea275bf05502d74d8d8396f8f51a4736c/work" + }, + "Name" => "overlay2" + } } - } - end + end From 9b91105a92b28d8396e1f1cfb14bca3092ee35e7 Mon Sep 17 00:00:00 2001 From: Deepa Kumaraswamy Date: Wed, 30 Mar 2022 17:09:22 +0530 Subject: [PATCH 13/13] doc changes Signed-off-by: Deepa Kumaraswamy --- docs-chef-io/content/inspec/resources/docker_image.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs-chef-io/content/inspec/resources/docker_image.md b/docs-chef-io/content/inspec/resources/docker_image.md index 933381bb1..9da692888 100644 --- a/docs-chef-io/content/inspec/resources/docker_image.md +++ b/docs-chef-io/content/inspec/resources/docker_image.md @@ -82,11 +82,9 @@ The `tag` property tests the value of the image tag. ### Low-level information of docker image as docker_image's property -#### Inspection +#### inspection -:inspection - - The property allows testing the low-level information of docker image returned by `docker inspect [docker_image]`. Use hash format `'key' => 'value` for testing the information. +The property allows testing the low-level information of docker image returned by `docker inspect [docker_image]`. Use hash format `'key' => 'value` for testing the information. its(:inspection) { should include "Key" => "Value" } its(:inspection) { should include "Key" => @@ -124,7 +122,7 @@ The `exist` matcher tests if the image is available on the node. ## Examples -### Test if a docker image exists and verifies the image properties: ID, image, repository, and tag +### Test if a docker image exists and verifies the image properties: ID, image, repo, and tag describe docker_image('ALPINE:LATEST') do it { should exist } @@ -134,7 +132,7 @@ The `exist` matcher tests if the image is available on the node. its('tag') { should eq 'LATEST' } end -### Test if a docker image exists and verifies the low-level information: Architecture, Config.Cmd, OS, and GraphDriver +### Test if a docker image exists and verifies the low-level information: Architecture, Config.Cmd, and GraphDriver describe docker_image('ubuntu:latest') do it { should exist }