github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/tests/test_jujuci.py (about)

     1  from argparse import Namespace
     2  import json
     3  import os
     4  from StringIO import StringIO
     5  import urllib2
     6  
     7  try:
     8      from mock import patch
     9  except ImportError:
    10      from unittest.mock import patch
    11  
    12  from jujuci import (
    13      acquire_binary,
    14      add_artifacts,
    15      Credentials,
    16      CredentialsMissing,
    17      find_artifacts,
    18      get_build_data,
    19      get_credentials,
    20      get_job_data,
    21      JENKINS_URL,
    22      JobNamer,
    23      list_artifacts,
    24      Namer,
    25      PackageNamer,
    26      main,
    27      setup_workspace,
    28  )
    29  from utility import temp_dir
    30  from tests import (
    31      FakeHomeTestCase,
    32      TestCase,
    33  )
    34  
    35  
    36  def make_build_data(number='lastSuccessfulBuild'):
    37      if number == 'lastSuccessfulBuild':
    38          number = 2112
    39      return {
    40          "actions": [
    41              {
    42                  "parameters": [
    43                      {
    44                          "name": "branch",
    45                          "value": "gitbranch:master:github.com/juju/juju"
    46                      },
    47                      {
    48                          "name": "revision",
    49                          "value": "3c53cf578ef100ba5368661224de4af5da72ee74"
    50                      }
    51                  ]
    52              },
    53              {
    54                  "causes": [
    55                      {
    56                          "shortDescription": "Started by user admin",
    57                          "userName": "admin"
    58                      }
    59                  ]
    60              },
    61              {},
    62              {}
    63          ],
    64          "artifacts": [
    65              {
    66                  "displayPath": "buildvars.bash",
    67                  "fileName": "buildvars.bash",
    68                  "relativePath": "buildvars.bash"
    69              },
    70              {
    71                  "displayPath": "buildvars.json",
    72                  "fileName": "buildvars.json",
    73                  "relativePath": "buildvars.json"
    74              },
    75              {
    76                  "displayPath": "juju-core_1.22-alpha1.tar.gz",
    77                  "fileName": "juju-core_1.22-alpha1.tar.gz",
    78                  "relativePath": "artifacts/juju-core_1.22-alpha1.tar.gz"
    79              }
    80          ],
    81          "building": False,
    82          "builtOn": "",
    83          "changeSet": {
    84              "items": [],
    85              "kind": None
    86          },
    87          "culprits": [],
    88          "description": "gitbranch:master:github.com/juju/juju 3c53cf57",
    89          "duration": 142986,
    90          "fullDisplayName": "build-revision #2102",
    91          "id": "2014-11-19_07-35-02",
    92          "keepLog": False,
    93          "number": 2102,
    94          "result": "SUCCESS",
    95          "timestamp": 1416382502379,
    96          "url": "http://jenkins:8080/job/build-revision/%s/" % number
    97      }
    98  
    99  
   100  def make_job_data():
   101      return {
   102          "actions": [
   103              {
   104                  "parameterDefinitions": [
   105                      {
   106                          "defaultParameterValue": {
   107                              "value": "1.18.1"
   108                          },
   109                          "description": "",
   110                          "name": "old_version",
   111                          "type": "StringParameterDefinition"
   112                      }
   113                  ]
   114              },
   115              {}
   116          ],
   117          "buildable": True,
   118          "builds": [
   119              {
   120                  "number": 1510,
   121                  "url": "http://jenkins:8080/job/ting/1510/"
   122              }
   123          ],
   124          "color": "red",
   125          "concurrentBuild": False,
   126          "description": "",
   127          "displayName": "ting",
   128          "downstreamProjects": [],
   129          "firstBuild": {
   130              "number": 1,
   131              "url": "http://jenkins:8080/job/ting/1/"
   132          },
   133          "healthReport": [
   134              {
   135                  "description": "Build stability: All recent builds failed.",
   136                  "iconUrl": "health-00to19.png",
   137                  "score": 0
   138              }
   139          ],
   140          "inQueue": False,
   141          "keepDependencies": False,
   142          "lastBuild": {
   143              "number": 1510,
   144              "url": "http://jenkins:8080/job/ting/1510/"
   145          },
   146          "lastCompletedBuild": {
   147              "number": 1510,
   148              "url": "http://jenkins:8080/job/ting/1510/"
   149          },
   150          "lastFailedBuild": {
   151              "number": 1510,
   152              "url": "http://jenkins:8080/job/ting/1510/"
   153          },
   154          "lastStableBuild": {
   155              "number": 1392,
   156              "url": "http://jenkins:8080/job/ting/1392/"
   157          },
   158          "lastSuccessfulBuild": {
   159              "number": 1392,
   160              "url": "http://jenkins:8080/job/ting/1392/"
   161          },
   162          "lastUnstableBuild": None,
   163          "lastUnsuccessfulBuild": {
   164              "number": 1510,
   165              "url": "http://jenkins:8080/job/ting/1510/"
   166          },
   167          "name": "ting",
   168          "nextBuildNumber": 1511,
   169          "property": [
   170              {},
   171              {
   172                  "parameterDefinitions": [
   173                      {
   174                          "defaultParameterValue": {
   175                              "name": "old_version",
   176                              "value": "1.18.1"
   177                          },
   178                          "description": "",
   179                          "name": "old_version",
   180                          "type": "StringParameterDefinition"
   181                      },
   182                  ]
   183              }
   184          ],
   185          "queueItem": None,
   186          "upstreamProjects": [],
   187          "url": "http://jenkins:8080/job/ting/"
   188      }
   189  
   190  
   191  class JujuCITestCase(FakeHomeTestCase):
   192  
   193      def test_get_credentials(self):
   194          self.assertEqual(
   195              get_credentials(Namespace(user='jrandom', password='password1')),
   196              Credentials('jrandom', 'password1'))
   197  
   198      def test_get_credentials_no_user(self):
   199          self.assertIs(get_credentials(Namespace()), None)
   200  
   201      def test_get_credentials_no_value(self):
   202          with self.assertRaisesRegexp(
   203                  CredentialsMissing,
   204                  'Jenkins username and/or password not supplied.'):
   205              get_credentials(Namespace(user=None, password='password1'))
   206          with self.assertRaisesRegexp(
   207                  CredentialsMissing,
   208                  'Jenkins username and/or password not supplied.'):
   209              get_credentials(Namespace(user='jrandom', password=None))
   210  
   211      def test_main_list_options(self):
   212          print_list = []
   213          with patch('jujuci.print_now', side_effect=print_list.append):
   214              with patch('jujuci.list_artifacts') as mock:
   215                  main(['-d', '-v', 'list', '-b', '1234', 'foo', '*.tar.gz',
   216                        '--user', 'jrandom', '--password', '1password'])
   217          args, kwargs = mock.call_args
   218          self.assertEqual((Credentials('jrandom', '1password'), 'foo',
   219                           '1234', '*.tar.gz'), args)
   220          self.assertTrue(kwargs['verbose'])
   221          self.assertEqual(print_list, ['Done.'])
   222  
   223      def test_main_setup_workspace_options(self):
   224          print_list = []
   225          with patch('jujuci.print_now', side_effect=print_list.append):
   226              with patch('jujuci.setup_workspace', autospec=True) as mock:
   227                  main(['-d', '-v', 'setup-workspace', './foo'])
   228          args, kwargs = mock.call_args
   229          self.assertEqual(('./foo', ), args)
   230          self.assertTrue(kwargs['dry_run'])
   231          self.assertTrue(kwargs['verbose'])
   232          self.assertEqual(print_list, ['Done.'])
   233  
   234      def test_get_build_data(self):
   235          expected_data = make_build_data(1234)
   236          json_io = StringIO(json.dumps(expected_data))
   237          with patch('urllib2.urlopen', return_value=json_io) as mock:
   238              build_data = get_build_data(
   239                  'http://foo:8080', Credentials('jrandom', '1password'), 'bar',
   240                  '1234')
   241          self.assertEqual(1, mock.call_count)
   242          request = mock.mock_calls[0][1][0]
   243          self.assertRequest(
   244              request, 'http://foo:8080/job/bar/1234/api/json',
   245              {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='})
   246          self.assertEqual(expected_data, build_data)
   247  
   248      def test_get_job_data(self):
   249          expected_data = make_job_data()
   250          json_io = StringIO(json.dumps(expected_data))
   251          with patch('urllib2.urlopen', return_value=json_io) as mock:
   252              build_data = get_job_data(
   253                  'http://foo:8080', Credentials('jrandom', '1password'), 'ting')
   254          self.assertEqual(1, mock.call_count)
   255          request = mock.mock_calls[0][1][0]
   256          self.assertRequest(
   257              request, 'http://foo:8080/job/ting/api/json',
   258              {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='})
   259          self.assertEqual(expected_data, build_data)
   260  
   261      def assertRequest(self, request, url, headers):
   262          self.assertIs(request.__class__, urllib2.Request)
   263          self.assertEqual(request.get_full_url(), url)
   264          self.assertEqual(request.headers, headers)
   265  
   266      def test_get_build_data_with_default_build(self):
   267          expected_data = make_build_data()
   268          json_io = StringIO(json.dumps(expected_data))
   269          with patch('urllib2.urlopen', return_value=json_io) as mock:
   270              get_build_data(
   271                  'http://foo:8080', Credentials('jrandom', '1password'), 'bar')
   272          self.assertEqual(mock.call_count, 1)
   273          self.assertRequest(
   274              mock.mock_calls[0][1][0],
   275              'http://foo:8080/job/bar/lastSuccessfulBuild/api/json',
   276              {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='})
   277  
   278      def test_find_artifacts_all(self):
   279          expected_data = make_build_data()
   280          artifacts = find_artifacts(expected_data)
   281          self.assertEqual(
   282              ['buildvars.bash', 'buildvars.json',
   283               'juju-core_1.22-alpha1.tar.gz'],
   284              sorted(a.file_name for a in artifacts))
   285  
   286      def test_find_artifacts_glob_tarball(self):
   287          expected_data = make_build_data()
   288          artifacts = find_artifacts(expected_data, '*.tar.gz')
   289          artifact = artifacts[0]
   290          self.assertEqual('juju-core_1.22-alpha1.tar.gz', artifact.file_name)
   291          self.assertEqual(
   292              'http://jenkins:8080/job/build-revision/2112/'
   293              'artifact/artifacts/juju-core_1.22-alpha1.tar.gz',
   294              artifact.location)
   295  
   296      def test_list_artifacts(self):
   297          credentials = Credentials('jrandom', '1password')
   298          build_data = make_build_data(1234)
   299          with patch('jujuci.get_build_data', return_value=build_data) as mock:
   300              with patch('jujuci.print_now') as pn_mock:
   301                  list_artifacts(credentials, 'foo', '1234', '*')
   302          mock.assert_called_once_with(JENKINS_URL, credentials, 'foo', '1234')
   303          files = sorted(call[1][0] for call in pn_mock.mock_calls)
   304          self.assertEqual(
   305              ['buildvars.bash', 'buildvars.json',
   306               'juju-core_1.22-alpha1.tar.gz'],
   307              files)
   308  
   309      def test_setup_workspace(self):
   310          with temp_dir() as base_dir:
   311              workspace_dir = os.path.join(base_dir, 'workspace')
   312              foo_dir = os.path.join(workspace_dir, 'foo')
   313              os.makedirs(foo_dir)
   314              with open(os.path.join(workspace_dir, 'old.txt'), 'w') as of:
   315                  of.write('old')
   316              print_list = []
   317              with patch('jujuci.print_now', side_effect=print_list.append):
   318                  setup_workspace(workspace_dir, dry_run=False, verbose=False)
   319              self.assertEqual(['artifacts'], os.listdir(workspace_dir))
   320              artifacts_dir = os.path.join(workspace_dir, 'artifacts')
   321              self.assertEqual(['empty'], os.listdir(artifacts_dir))
   322              self.assertEqual(
   323                  print_list,
   324                  ['Removing old.txt', 'Removing foo', 'Creating artifacts dir.']
   325              )
   326  
   327      def test_add_artifacts_simple(self):
   328          with temp_dir() as workspace_dir:
   329              artifacts_dir = os.path.join(workspace_dir, 'artifacts')
   330              os.mkdir(artifacts_dir)
   331              for name in ['foo.tar.gz', 'bar.json', 'baz.txt',
   332                           'juju-core_1.2.3.tar.gz', 'juju-core-1.2.3.deb',
   333                           'buildvars.bash', 'buildvars.json']:
   334                  with open(os.path.join(workspace_dir, name), 'w') as nf:
   335                      nf.write(name)
   336              globs = ['buildvars.*', 'juju-core_*.tar.gz', 'juju-*.deb']
   337              add_artifacts(
   338                  workspace_dir, globs, dry_run=False, verbose=False)
   339              artifacts = sorted(os.listdir(artifacts_dir))
   340              expected = [
   341                  'buildvars.bash', 'buildvars.json',
   342                  'juju-core-1.2.3.deb', 'juju-core_1.2.3.tar.gz']
   343              self.assertEqual(expected, artifacts)
   344  
   345      def test_add_artifacts_deep(self):
   346          with temp_dir() as workspace_dir:
   347              artifacts_dir = os.path.join(workspace_dir, 'artifacts')
   348              os.mkdir(artifacts_dir)
   349              sub_dir = os.path.join(workspace_dir, 'sub_dir')
   350              os.mkdir(sub_dir)
   351              for name in ['foo.tar.gz', 'juju-core-1.2.3.deb']:
   352                  with open(os.path.join(sub_dir, name), 'w') as nf:
   353                      nf.write(name)
   354              add_artifacts(
   355                  workspace_dir, ['sub_dir/*.deb'], dry_run=False, verbose=False)
   356              artifacts = os.listdir(artifacts_dir)
   357              self.assertEqual(['juju-core-1.2.3.deb'], artifacts)
   358  
   359  
   360  class TestNamer(TestCase):
   361  
   362      def test_factory(self):
   363          with patch('subprocess.check_output', return_value=' amd42 \n'):
   364              with patch('jujuci.get_distro_information',
   365                         return_value={'RELEASE': '42.42', 'CODENAME': 'wacky'}):
   366                  namer = Namer.factory()
   367          self.assertIs(type(namer), Namer)
   368          self.assertEqual(namer.arch, 'amd42')
   369          self.assertEqual(namer.distro_release, '42.42')
   370          self.assertEqual(namer.distro_series, 'wacky')
   371  
   372  
   373  class TestPackageNamer(TestNamer):
   374  
   375      def test_get_release_package(self):
   376          package_namer = PackageNamer('amd42', '42.34', 'wacky')
   377          self.assertEqual(
   378              package_namer.get_release_package('27.6'),
   379              'juju-core_27.6-0ubuntu1~42.34.1~juju1_amd42.deb')
   380  
   381      def test_get_certification_package(self):
   382          package_namer = PackageNamer('amd42', '42.34', 'wacky')
   383          self.assertEqual(
   384              package_namer.get_certification_package('27.6~0ubuntu1'),
   385              'juju-core_27.6~0ubuntu1~42.34.1_amd42.deb')
   386  
   387  
   388  class TestJobNamer(TestNamer):
   389  
   390      def test_get_build_binary(self):
   391          self.assertEqual(
   392              JobNamer('ppc64el', '42.34', 'wacky').get_build_binary_job(),
   393              'build-binary-wacky-ppc64el')
   394  
   395  
   396  class TestAcquireBinary(TestCase):
   397  
   398      def fake_call(self, args, parent='bin'):
   399          dest = args[3]
   400          parent_path = os.path.join(dest, 'bar', parent)
   401          os.makedirs(parent_path)
   402          bin_path = os.path.join(parent_path, 'juju')
   403          open(bin_path, 'w').close()
   404  
   405      def fake_call_completion(self, args):
   406          return self.fake_call(args, parent='bash_completion.d')
   407  
   408      def test_avoids_bash_completion(self):
   409          with temp_dir() as workspace:
   410              with patch('subprocess.check_call',
   411                         side_effect=self.fake_call_completion):
   412                  result = acquire_binary(None, workspace)
   413          self.assertIs(None, result)