2017-03-21 09:03:06 -05:00
#pylint: skip-file
2015-07-08 16:30:14 -04:00
import unittest
import selinux
2017-01-25 13:26:27 -06:00
import sys
2015-07-08 16:30:14 -04:00
from Atomic import util
2017-03-21 09:03:06 -05:00
from Atomic . backends . _docker import DockerBackend
import time
2017-05-12 10:53:57 -04:00
import os
2017-10-24 10:46:24 +02:00
import re
2017-03-21 09:03:06 -05:00
no_mock = True
try :
from unittest . mock import MagicMock , patch
no_mock = False
except ImportError :
try :
from mock import MagicMock , patch
no_mock = False
except ImportError :
# Mock is already set to False
pass
2015-07-08 16:30:14 -04:00
2017-01-25 13:26:27 -06:00
def _new_enough ( ) :
py_version = sys . version_info
if ( py_version . major , py_version . minor , py_version . micro ) > = ( 2 , 7 , 6 ) :
return True
return False
new_enough = _new_enough ( )
2015-07-08 16:30:14 -04:00
2017-03-21 09:03:06 -05:00
if no_mock :
# If there is no mock, we need need to create a fake
# patch decorator
def fake_patch ( a , new = ' ' ) :
def foo ( func ) :
def wrapper ( * args , * * kwargs ) :
ret = func ( * args , * * kwargs )
return ret
return wrapper
return foo
patch = fake_patch
2015-07-08 16:30:14 -04:00
class TestAtomicUtil ( unittest . TestCase ) :
2016-10-04 13:56:55 -05:00
2015-07-08 16:30:14 -04:00
def test_image_by_name ( self ) :
matches = util . image_by_name ( ' atomic-test-1 ' )
self . assertEqual ( len ( matches ) , 1 )
self . assertEqual ( matches [ 0 ] [ ' Labels ' ] [ ' Name ' ] ,
' atomic-test-1 ' )
def test_image_by_name_glob ( self ) :
matches = util . image_by_name ( ' atomic-test-* ' )
self . assertTrue ( len ( matches ) > 2 )
self . assertTrue ( all ( [ m [ ' Labels ' ] [ ' Name ' ] . startswith ( ' atomic-test- ' )
for m in matches ] ) )
def test_image_by_name_registry_match ( self ) :
2015-11-16 17:15:42 -05:00
matches = util . image_by_name ( ' /centos:latest ' )
2015-07-08 16:30:14 -04:00
self . assertTrue ( len ( matches ) == 1 )
def test_image_by_name_no_match ( self ) :
matches = util . image_by_name ( ' this is not a real image name ' )
self . assertTrue ( len ( matches ) == 0 )
def test_default_container_context ( self ) :
2016-11-22 11:40:11 -05:00
default = util . default_container_context ( )
if selinux . is_selinux_enabled ( ) :
# newer policies use container_file_t
self . assertTrue ( default in
[ ' system_u:object_r:container_file_t:s0 ' ,
' system_u:object_r:svirt_sandbox_file_t:s0 ' ] )
else :
self . assertEqual ( default , ' ' )
2015-07-08 16:30:14 -04:00
2016-08-10 13:37:51 +02:00
def test_check_call ( self ) :
exception_raised = False
try :
util . check_call ( [ ' /usr/bin/does_not_exist ' ] )
except util . FileNotFound :
exception_raised = True
self . assertTrue ( exception_raised )
def test_call ( self ) :
exception_raised = False
try :
util . call ( [ ' /usr/bin/does_not_exist ' ] )
except util . FileNotFound :
exception_raised = True
self . assertTrue ( exception_raised )
def test_check_output ( self ) :
exception_raised = False
try :
util . check_call ( [ ' /usr/bin/does_not_exist ' ] )
except util . FileNotFound :
exception_raised = True
self . assertTrue ( exception_raised )
2015-07-08 16:30:14 -04:00
2016-10-04 13:56:55 -05:00
def test_decompose ( self ) :
2016-10-12 08:22:13 -05:00
images = [ ( ' docker.io/library/busybox ' , ( ' docker.io ' , ' library ' , ' busybox ' , ' latest ' , ' ' ) ) ,
( ' docker.io/library/foobar/busybox ' , ( ' docker.io ' , ' library/foobar ' , ' busybox ' , ' latest ' , ' ' ) ) ,
( ' docker.io/library/foobar/busybox:2.1 ' , ( ' docker.io ' , ' library/foobar ' , ' busybox ' , ' 2.1 ' , ' ' ) ) ,
( ' docker.io/busybox:2.1 ' , ( ' docker.io ' , ' library ' , ' busybox ' , ' 2.1 ' , ' ' ) ) ,
( ' docker.io/busybox ' , ( ' docker.io ' , ' library ' , ' busybox ' , ' latest ' , ' ' ) ) ,
2018-03-08 13:42:05 +03:00
( ' docker.io:5000/busybox ' , ( ' docker.io:5000 ' , ' ' , ' busybox ' , ' latest ' , ' ' ) ) ,
( ' docker.io:5000/library/busybox:2.1 ' , ( ' docker.io:5000 ' , ' library ' , ' busybox ' , ' 2.1 ' , ' ' ) ) ,
2016-10-12 08:22:13 -05:00
( ' busybox ' , ( ' ' , ' ' , ' busybox ' , ' latest ' , ' ' ) ) ,
( ' busybox:2.1 ' , ( ' ' , ' ' , ' busybox ' , ' 2.1 ' , ' ' ) ) ,
( ' library/busybox ' , ( ' ' , ' library ' , ' busybox ' , ' latest ' , ' ' ) ) ,
( ' library/busybox:2.1 ' , ( ' ' , ' library ' , ' busybox ' , ' 2.1 ' , ' ' ) ) ,
( ' registry.access.redhat.com/rhel7:latest ' , ( ' registry.access.redhat.com ' , ' ' , ' rhel7 ' , ' latest ' , ' ' ) ) ,
( ' registry.access.redhat.com/rhel7 ' , ( ' registry.access.redhat.com ' , ' ' , ' rhel7 ' , ' latest ' , ' ' ) ) ,
( ' fedora@sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e ' , ( ' ' , ' ' , ' fedora ' , ' ' , ' sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e ' ) ) ,
( ' docker.io/library/fedora@sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e ' , ( ' docker.io ' , ' library ' , ' fedora ' , ' ' , ' sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e ' ) ) ,
( ' docker.io/fedora@sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e ' , ( ' docker.io ' , ' library ' , ' fedora ' , ' ' , ' sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e ' ) )
2016-10-04 13:56:55 -05:00
]
for image in images :
2016-10-12 08:22:13 -05:00
self . assertEqual ( util . Decompose ( image [ 0 ] ) . all , image [ 1 ] )
2016-10-04 13:56:55 -05:00
2017-01-25 13:26:27 -06:00
@unittest.skipUnless ( new_enough , " Requires 2.7.6 or newer " )
2017-01-06 16:27:00 -05:00
def test_valid_uri ( self ) :
2017-01-10 10:36:19 -05:00
valid_uris = [ ' example.com ' , ' example.com:5000 ' , ' example.US.com ' , ' example.com/image/name:version1 ' , ' example.com:5000/foo/bar/image:tag ' , ' example_inc.com ' ]
2017-02-14 09:58:40 -05:00
invalid_uris = [ ' example.com/Image/name ' , ' example.com/image(name):latest ' , ' example.com/foo_bar ' , ' example[us].com ' , ' example.com#foo/bar ' ]
2017-01-06 16:27:00 -05:00
for uri in valid_uris :
2017-01-10 10:36:19 -05:00
self . assertTrue ( util . is_valid_image_uri ( uri ) )
2017-01-06 16:27:00 -05:00
for uri in invalid_uris :
exception_raised = False
try :
2017-01-10 10:36:19 -05:00
util . is_valid_image_uri ( uri )
2017-01-06 16:27:00 -05:00
except ValueError :
exception_raised = True
self . assertTrue ( exception_raised )
2016-10-04 13:56:55 -05:00
2017-05-12 10:53:57 -04:00
def test_set_proxy_default ( self ) :
# Make the test call
proxies = util . set_proxy ( )
# ensure each expected item exists
for item in ( ' http ' , ' https ' , ' no_proxy ' ) :
self . assertIn ( item , proxies . keys ( ) )
def test_set_proxy_with_items ( self ) :
orig_environ = os . environ
# Set all three
for item in ( ' HTTP_PROXY ' , ' HTTPS_PROXY ' , ' NO_PROXY ' ) :
os . environ [ item ] = item
# Make the test call
proxies = util . set_proxy ( )
# Check each is set
for key , val in (
( ' http ' , ' HTTP_PROXY ' ) ,
( ' https ' , ' HTTPS_PROXY ' ) ,
( ' no_proxy ' , ' NO_PROXY ' ) ) :
self . assertEquals ( val , proxies [ key ] )
# Reset environ back to the original
os . environ = orig_environ
def test_get_proxy_defaults ( self ) :
proxies = util . get_proxy ( )
# ensure each expected item exists
for item in ( ' http ' , ' https ' , ' no_proxy ' ) :
self . assertIn ( item , proxies . keys ( ) )
def test_get_proxy_with_items ( self ) :
orig_environ = os . environ
# Set all three
for item in ( ' HTTP_PROXY ' , ' HTTPS_PROXY ' , ' NO_PROXY ' ) :
os . environ [ item ] = item
# Make the test call
proxies = util . get_proxy ( )
# Check each is set
for key , val in (
( ' http ' , ' HTTP_PROXY ' ) ,
( ' https ' , ' HTTPS_PROXY ' ) ,
( ' no_proxy ' , ' NO_PROXY ' ) ) :
self . assertEquals ( val , proxies [ key ] )
# Reset environ back to the original
os . environ = orig_environ
2017-10-24 10:46:24 +02:00
def test_get_all_known_process_capabilities ( self ) :
capabilities = util . get_all_known_process_capabilities ( )
for item in [ ' CAP_CHOWN ' , ' CAP_SYS_ADMIN ' , ' CAP_MKNOD ' ] :
self . assertIn ( item , capabilities )
# Check that all the capabilities held by PID 1 are known.
with open ( ' /proc/1/status ' , ' r ' ) as f :
content = f . read ( )
bounding_set = re . search ( r ' CapBnd: \ t(.*) \ n ' , content , re . M | re . I ) . group ( 1 )
out = util . check_output ( [ ' capsh ' , ' --decode= %s ' % bounding_set ] ) . decode ( )
out = str ( out . split ( " = " ) [ 1 ] )
for i in out . strip ( ) . split ( ' , ' ) :
if not i [ 0 ] . isdigit ( ) :
self . assertIn ( i . upper ( ) , capabilities )
2017-03-21 09:03:06 -05:00
class MockIO ( object ) :
2018-03-23 22:24:37 +01:00
original_data = { " install_test " : [ { " install_date " : " 2017-03-22 17:19:41 " , " id " : " 49779293ca711789a77bbdc35547a6b9ecb193a51b4e360fea95c4d206605d18 " } ] }
new_data_fq = [ { " install_date " : " 2017-04-22 17:19:41 " , " id " : " 16e9fdecc1febc87fb1ca09271009cf5f28eb8d4aec5515922ef298c145a6726 " } ]
new_data_name = [ { " install_date " : " 2017-04-22 17:19:41 " , " id " : " 16e9fdecc1febc87fb1ca09271009cf5f28eb8d4aec5515922ef298c145a6726 " } ]
2017-03-21 09:03:06 -05:00
install_data = original_data
@classmethod
def read_mock ( cls ) :
return cls . install_data
@classmethod
def write_mock ( cls , val ) :
cls . install_data = val
@classmethod
def reset_data ( cls ) :
cls . install_data = cls . original_data
@classmethod
def grow_data ( cls , var_name , name ) :
cls . install_data [ name ] = getattr ( cls , var_name )
local_centos_inspect = { ' Id ' : ' 16e9fdecc1febc87fb1ca09271009cf5f28eb8d4aec5515922ef298c145a6726 ' , ' RepoDigests ' : [ ' docker.io/centos@sha256:7793b39617b28c6cd35774c00383b89a1265f3abf6efcaf0b8f4aafe4e0662d2 ' ] , ' Parent ' : ' ' , ' GraphDriver ' : { ' Name ' : ' devicemapper ' , ' Data ' : { ' DeviceSize ' : ' 10737418240 ' , ' DeviceName ' : ' docker-253:2-5900125-3fb5b406e6a53142129237c9e2c3a1ce8b6cf269b5f8071fcd62107c41544cd2 ' , ' DeviceId ' : ' 779 ' } } , ' Created ' : ' 2016-08-30T18:20:19.39890162Z ' , ' Comment ' : ' ' , ' DockerVersion ' : ' 1.12.1 ' , ' VirtualSize ' : 210208812 , ' Author ' : ' The CentOS Project <cloud-ops@centos.org> - ami_creator ' , ' Os ' : ' linux ' , ' RootFS ' : { ' Type ' : ' layers ' , ' Layers ' : [ ' 5fa0fa02637842ab1ddc8b3a17b86691c87c87d20800e6a95a113343f6ffd84c ' ] } , ' Container ' : ' a5b0819aa82c224095e1a18e9df0776a7b38d32bacca073f054723b65fb54f0e ' , ' Architecture ' : ' amd64 ' , ' RepoTags ' : [ ' docker.io/centos:centos7.0.1406 ' ] , ' Config ' : { ' Labels ' : { } , ' Entrypoint ' : None , ' StdinOnce ' : False , ' OnBuild ' : None , ' Env ' : [ ' PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ' ] , ' Volumes ' : None , ' Cmd ' : None , ' User ' : ' ' , ' AttachStdin ' : False , ' AttachStderr ' : False , ' AttachStdout ' : False , ' WorkingDir ' : ' ' , ' Tty ' : False , ' Image ' : ' 20ae10d641a0af6f25ceaa75fdcf591d171e3c521a54a3f3a2868b602d735e11 ' , ' Hostname ' : ' a5b0819aa82c ' , ' Domainname ' : ' ' , ' OpenStdin ' : False } , ' Size ' : 210208812 , ' ContainerConfig ' : { ' Labels ' : { } , ' Entrypoint ' : None , ' StdinOnce ' : False , ' OnBuild ' : None , ' Env ' : [ ' PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ' ] , ' Volumes ' : None , ' Cmd ' : [ ' /bin/sh ' , ' -c ' , ' #(nop) ADD file:6a409eac27f0c7e04393da096dbeff01b929405e79b15222a0dc06a2084d3df3 in / ' ] , ' User ' : ' ' , ' AttachStdin ' : False , ' AttachStderr ' : False , ' AttachStdout ' : False , ' WorkingDir ' : ' ' , ' Tty ' : False , ' Image ' : ' 20ae10d641a0af6f25ceaa75fdcf591d171e3c521a54a3f3a2868b602d735e11 ' , ' Hostname ' : ' a5b0819aa82c ' , ' Domainname ' : ' ' , ' OpenStdin ' : False } }
rhel_docker_inspect = { u ' Comment ' : u ' ' , u ' Container ' : u ' ' , u ' DockerVersion ' : u ' 1.9.1 ' , u ' Parent ' : u ' ' , u ' Created ' : u ' 2016-10-26T12:02:33.368772Z ' , u ' Config ' : { u ' Tty ' : False , u ' Cmd ' : [ u ' /bin/bash ' ] , u ' Volumes ' : None , u ' Domainname ' : u ' ' , u ' WorkingDir ' : u ' ' , u ' Image ' : u ' f6f6121b053b2312688c87d3a1d32d06a984dc01d2ea7738508a50581cddb6b4 ' , u ' Hostname ' : u ' ' , u ' StdinOnce ' : False , u ' Labels ' : { u ' com.redhat.component ' : u ' rhel-server-docker ' , u ' authoritative-source-url ' : u ' registry.access.redhat.com ' , u ' distribution-scope ' : u ' public ' , u ' Vendor ' : u ' Red Hat, Inc. ' , u ' Name ' : u ' rhel7/rhel ' , u ' Build_Host ' : u ' rcm-img01.build.eng.bos.redhat.com ' , u ' vcs-type ' : u ' git ' , u ' name ' : u ' rhel7/rhel ' , u ' vcs-ref ' : u ' 7eeaf203cf909c2c056fba7066db9c1073a28d97 ' , u ' release ' : u ' 45 ' , u ' Version ' : u ' 7.3 ' , u ' Architecture ' : u ' x86_64 ' , u ' version ' : u ' 7.3 ' , u ' Release ' : u ' 45 ' , u ' vendor ' : u ' Red Hat, Inc. ' , u ' BZComponent ' : u ' rhel-server-docker ' , u ' build-date ' : u ' 2016-10-26T07:54:17.037911Z ' , u ' com.redhat.build-host ' : u ' ip-10-29-120-48.ec2.internal ' , u ' architecture ' : u ' x86_64 ' } , u ' AttachStdin ' : False , u ' User ' : u ' ' , u ' Env ' : [ u ' PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ' , u ' container=docker ' ] , u ' Entrypoint ' : None , u ' OnBuild ' : [ ] , u ' AttachStderr ' : False , u ' AttachStdout ' : False , u ' OpenStdin ' : False } , u ' Author ' : u ' Red Hat, Inc. ' , u ' GraphDriver ' : { u ' Data ' : { u ' DeviceName ' : u ' docker-253:2-5900125-a2bce97a4fd7ea12dce9865caa461ead8d1caf51ef452aba2f1b9d98efdf968f ' , u ' DeviceSize ' : u ' 10737418240 ' , u ' DeviceId ' : u ' 623 ' } , u ' Name ' : u ' devicemapper ' } , u ' VirtualSize ' : 192508958 , u ' Os ' : u ' linux ' , u ' Architecture ' : u ' amd64 ' , u ' RootFS ' : { u ' Layers ' : [ u ' 34d3e0e77091d9d51c6f70a7a7a4f7536aab214a55e02a8923af8f80cbe60d30 ' , u ' ccd6fc81ec49bd45f04db699401eb149b1945bb7292476b390ebdcdd7d975697 ' ] , u ' Type ' : u ' layers ' } , u ' ContainerConfig ' : { u ' Tty ' : False , u ' Cmd ' : None , u ' Volumes ' : None , u ' Domainname ' : u ' ' , u ' WorkingDir ' : u ' ' , u ' Image ' : u ' ' , u ' Hostname ' : u ' ' , u ' StdinOnce ' : False , u ' Labels ' : None , u ' AttachStdin ' : False , u ' User ' : u ' ' , u ' Env ' : None , u ' Entrypoint ' : None , u ' OnBuild ' : None , u ' AttachStderr ' : False , u ' AttachStdout ' : False , u ' OpenStdin ' : False } , u ' Size ' : 192508958 , u ' RepoDigests ' : [ u ' registry.access.redhat.com/rhel7@sha256:da8a3e9297da7ccd1948366103d13c45b7e77489382351a777a7326004b63a21 ' ] , u ' Id ' : u ' f98706e16e41e56c4beaeea9fa77cd00fe35693635ed274f128876713afc0a1e ' , u ' RepoTags ' : [ u ' registry.access.redhat.com/rhel7:latest ' ] }
@unittest.skipIf ( no_mock , " Mock not found " )
class InstallData ( unittest . TestCase ) :
class Args ( ) :
def __init__ ( self ) :
self . storage = None
self . debug = False
self . name = None
self . image = None
@patch ( ' Atomic.util.InstallData.read_install_data ' , new = MockIO . read_mock )
@patch ( ' Atomic.util.InstallData.write_install_data ' , new = MockIO . write_mock )
def test_read ( self ) :
MockIO . reset_data ( )
self . assertEqual ( util . InstallData . read_install_data ( ) , MockIO . install_data )
@patch ( ' Atomic.util.InstallData.read_install_data ' , new = MockIO . read_mock )
@patch ( ' Atomic.util.InstallData.write_install_data ' , new = MockIO . write_mock )
def test_write ( self ) :
MockIO . reset_data ( )
install_data = util . InstallData . read_install_data ( )
install_data [ ' docker.io/library/centos:latest ' ] = MockIO . new_data_fq
util . InstallData . write_install_data ( install_data )
self . assertTrue ( ' docker.io/library/centos:latest ' in util . InstallData . read_install_data ( ) )
@patch ( ' Atomic.util.InstallData.read_install_data ' , new = MockIO . read_mock )
@patch ( ' Atomic.util.InstallData.write_install_data ' , new = MockIO . write_mock )
def test_get_install_name_by_id ( self ) :
MockIO . reset_data ( )
MockIO . grow_data ( ' new_data_fq ' , ' docker.io/library/centos:latest ' )
self . assertEqual ( util . InstallData . get_install_name_by_id ( ' 16e9fdecc1febc87fb1ca09271009cf5f28eb8d4aec5515922ef298c145a6726 ' , install_data = MockIO . install_data ) , ' docker.io/library/centos:latest ' )
@patch ( ' Atomic.util.InstallData.read_install_data ' , new = MockIO . read_mock )
@patch ( ' Atomic.util.InstallData.write_install_data ' , new = MockIO . write_mock )
def test_fail_get_install_name_by_id ( self ) :
MockIO . reset_data ( )
self . assertRaises ( ValueError , util . InstallData . get_install_name_by_id , 1 , MockIO . install_data )
@patch ( ' Atomic.util.InstallData.read_install_data ' , new = MockIO . read_mock )
@patch ( ' Atomic.util.InstallData.write_install_data ' , new = MockIO . write_mock )
def test_image_installed_name ( self ) :
MockIO . reset_data ( )
MockIO . grow_data ( ' new_data_fq ' , ' docker.io/library/centos:latest ' )
args = self . Args ( )
args . storage = ' docker '
args . image = ' docker.io/library/centos:latest '
db = DockerBackend ( )
db . _inspect_image = MagicMock ( return_value = local_centos_inspect )
local_image_object = db . inspect_image ( args . image )
self . assertTrue ( util . InstallData . image_installed ( local_image_object ) )
@patch ( ' Atomic.util.InstallData.read_install_data ' , new = MockIO . read_mock )
@patch ( ' Atomic.util.InstallData.write_install_data ' , new = MockIO . write_mock )
def test_image_installed_id ( self ) :
MockIO . reset_data ( )
MockIO . grow_data ( ' new_data_fq ' , ' 16e9fdecc1febc87fb1ca09271009cf5f28eb8d4aec5515922ef298c145a6726 ' )
args = self . Args ( )
args . storage = ' docker '
args . image = ' docker.io/library/centos:latest '
db = DockerBackend ( )
db . _inspect_image = MagicMock ( return_value = local_centos_inspect )
local_image_object = db . inspect_image ( args . image )
self . assertTrue ( util . InstallData . image_installed ( local_image_object ) )
@patch ( ' Atomic.util.InstallData.read_install_data ' , new = MockIO . read_mock )
@patch ( ' Atomic.util.InstallData.write_install_data ' , new = MockIO . write_mock )
def test_image_not_installed ( self ) :
MockIO . reset_data ( )
args = self . Args ( )
args . storage = ' docker '
args . image = ' registry.access.redhat.com/rhel7 '
db = DockerBackend ( )
db . _inspect_image = MagicMock ( return_value = rhel_docker_inspect )
local_image_object = db . inspect_image ( args . image )
self . assertFalse ( util . InstallData . image_installed ( local_image_object ) )
2015-07-08 16:30:14 -04:00
if __name__ == ' __main__ ' :
unittest . main ( )