def test_create_key_already_registered(self, mock_installed,
                                           mock_check_output,
                                           mock_get_account_information,
                                           mock_check_call):
        mock_installed.return_value = True
        mock_check_output.side_effect = mock_snap_output
        mock_get_account_information.return_value = {
            'account_id':
            'abcd',
            'account_keys': [
                {
                    'name': 'new-key',
                    'public-key-sha3-384':
                    (get_sample_key('default')['sha3-384']),
                },
            ],
        }

        with self.assertRaises(SystemExit) as raised:
            main(['create-key', 'new-key'])

        self.assertEqual(0, mock_check_call.call_count)
        self.assertEqual(1, raised.exception.code)
        self.assertIn('You have already registered a key named "new-key".',
                      self.fake_logger.output)
    def test_release_with_bad_channel_info(self):
        patcher = mock.patch.object(storeapi.StoreClient, 'release')
        mock_release = patcher.start()
        self.addCleanup(patcher.stop)
        mock_release.return_value = {
            'channel_map': [{
                'channel': 'stable',
                'info': 'fake-bad-channel-info'
            }, {
                'channel': 'candidate',
                'info': 'none'
            }, {
                'revision': 19,
                'channel': 'beta',
                'version': '0',
                'info': 'specific'
            }, {
                'channel': 'edge',
                'info': 'tracking'
            }]
        }

        with self.assertRaises(SystemExit):
            main(['release', 'nil-snap', '19', 'beta'])

        self.assertIn('Unexpected channel info \'fake-bad-channel-info\'.',
                      self.fake_logger.output)
    def test_list_plugins_non_tty(self):
        self.maxDiff = None
        fake_terminal = fixture_setup.FakeTerminal(isatty=False)
        self.useFixture(fake_terminal)

        main(['list-plugins'])
        self.assertEqual(fake_terminal.getvalue(), self.default_plugin_output)
Beispiel #4
0
    def test_init_must_write_snapcraft_yaml(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        expected_yaml = """name: my-snap-name # you probably want to 'snapcraft register <name>'
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
description: |
  This is my-snap's description. You have a paragraph or two to tell the
  most important story about your snap. Keep it under 100 words though,
  we live in tweetspace and your description wants to look good in the snap
  store.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil"""  # noqa, lines too long

        main(['init'])

        self.assertEqual(
            'Created snap/snapcraft.yaml.\nEdit the file to your liking or '
            'run `snapcraft` to get started\n', fake_logger.output)

        # Verify the generated yaml
        with open(os.path.join('snap', 'snapcraft.yaml'), 'r') as f:
            self.assertEqual(f.read(), expected_yaml)
Beispiel #5
0
    def test_list_keys_successfully(self, mock_installed, mock_check_output,
                                    mock_get_account_information):
        mock_installed.return_value = True
        mock_check_output.side_effect = mock_snap_output
        mock_get_account_information.return_value = {
            'account_id':
            'abcd',
            'account_keys': [
                {
                    'name': 'default',
                    'public-key-sha3-384':
                    (get_sample_key('default')['sha3-384']),
                },
            ],
        }

        main([self.command_name])

        expected_output = dedent('''\
                Name     SHA3-384 fingerprint
            *   default  {default_sha3_384}
            -   another  {another_sha3_384}  (not registered)
            ''').format(default_sha3_384=get_sample_key('default')['sha3-384'],
                        another_sha3_384=get_sample_key('another')['sha3-384'])
        self.assertIn(expected_output, self.fake_terminal.getvalue())
Beispiel #6
0
    def test_sign_build_no_usable_named_key(
            self, mock_installed, mock_get_snap_data, mock_check_output,
            mock_get_account_info):
        mock_installed.return_value = True
        mock_get_account_info.return_value = {
            'account_id': 'abcd',
            'snaps': {
                '16': {
                    'test-snap': {'snap-id': 'snap-id'},
                }
            }
        }
        mock_get_snap_data.return_value = {
            'name': 'test-snap',
            'grade': 'stable',
        }
        mock_check_output.side_effect = [
            '[{"name": "default"}]',
        ]

        with self.assertRaises(SystemExit) as raised:
            main(['sign-build', '--key-name', 'zoing',
                  self.snap_test.snap_path])

        self.assertEqual(1, raised.exception.code)
        self.assertEqual([
            'You have no usable key named "zoing".',
            'See the keys available in your system with `snapcraft keys`.'
        ], self.fake_logger.output.splitlines())

        snap_build_path = self.snap_test.snap_path + '-build'
        self.assertFalse(os.path.exists(snap_build_path))
Beispiel #7
0
    def test_sign_build_push_existing(
            self, mock_installed, mock_get_snap_data, mock_get_account_info,
            mock_push_snap_build):
        mock_installed.return_value = True
        mock_get_account_info.return_value = {
            'account_id': 'abcd',
            'snaps': {
                '16': {
                    'test-snap': {'snap-id': 'snap-id'},
                }
            }
        }
        mock_get_snap_data.return_value = {
            'name': 'test-snap',
            'grade': 'stable',
        }

        snap_build_path = self.snap_test.snap_path + '-build'
        with open(snap_build_path, 'wb') as fd:
            fd.write(b'Already signed assertion')

        main(['sign-build', self.snap_test.snap_path])

        self.assertEqual([
            'A signed build assertion for this snap already exists.',
            'Build assertion {} pushed to the Store.'.format(snap_build_path),
        ], self.fake_logger.output.splitlines())
        mock_push_snap_build.assert_called_with(
            'snap-id', 'Already signed assertion')
    def test_status_with_no_permissions(self):
        with self.assertRaises(SystemExit):
            main(['status', 'snap-test'])

        self.assertIn(
            'No valid credentials found. Have you run "snapcraft login"?',
            self.fake_logger.output)
Beispiel #9
0
    def test_init_must_write_snapcraft_yaml(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        expected_yaml = """name: my-snap-name # you probably want to 'snapcraft register <name>'
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
description: |
  This is my-snap's description. You have a paragraph or two to tell the
  most important story about your snap. Keep it under 100 words though,
  we live in tweetspace and your description wants to look good in the snap
  store.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil\n"""  # noqa, lines too long

        main(['init'])

        self.assertEqual(
            'Created snap/snapcraft.yaml.\nEdit the file to your liking or '
            'run `snapcraft` to get started\n', fake_logger.output)

        # Verify the generated yaml
        with open(os.path.join('snap', 'snapcraft.yaml'), 'r') as f:
            self.assertEqual(f.read(), expected_yaml)
Beispiel #10
0
    def test_stage_ran_twice_is_a_noop(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)
        parts = self.make_snapcraft_yaml()

        main(['stage'])

        self.assertEqual(
            'Preparing to pull stage0 \n'
            'Pulling stage0 \n'
            'Preparing to build stage0 \n'
            'Building stage0 \n'
            'Staging stage0 \n',
            fake_logger.output)

        self.assertTrue(os.path.exists(self.stage_dir),
                        'Expected a stage directory')
        self.assertTrue(os.path.exists(self.parts_dir),
                        'Expected a parts directory')
        self.assertTrue(os.path.exists(parts[0]['part_dir']),
                        'Expected a part directory for the build0 part')

        self.verify_state('build0', parts[0]['state_dir'], 'stage')

        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        main(['stage'])

        self.assertEqual(
            'Skipping pull stage0 (already ran)\n'
            'Skipping build stage0 (already ran)\n'
            'Skipping stage stage0 (already ran)\n',
            fake_logger.output)
Beispiel #11
0
    def test_snap_renames_stale_snap_build(self, mocked_time):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)
        self.make_snapcraft_yaml()

        mocked_time.return_value = 1234

        snap_build = 'snap-test_1.0_amd64.snap-build'
        with open(snap_build, 'w') as fd:
            fd.write('signed assertion?')

        main(['snap'])

        snap_build_renamed = snap_build + '.1234'
        self.assertEqual([
            'Preparing to pull part1 ',
            'Pulling part1 ',
            'Preparing to build part1 ',
            'Building part1 ',
            'Staging part1 ',
            'Priming part1 ',
            'Renaming stale build assertion to {}'.format(snap_build_renamed),
            'Snapping \'snap-test\' ...',
            'Snapped snap-test_1.0_amd64.snap',
            ], fake_logger.output.splitlines())

        self.assertThat('snap-test_1.0_amd64.snap', FileExists())
        self.assertThat(snap_build, Not(FileExists()))
        self.assertThat(snap_build_renamed, FileExists())
        self.assertThat(
            snap_build_renamed, FileContains('signed assertion?'))
Beispiel #12
0
    def test_snap_defaults(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)
        self.make_snapcraft_yaml()

        main(['snap'])

        self.assertEqual(
            'Preparing to pull part1 \n'
            'Pulling part1 \n'
            'Preparing to build part1 \n'
            'Building part1 \n'
            'Staging part1 \n'
            'Priming part1 \n'
            'Snapping \'snap-test\' ...\n'
            'Snapped snap-test_1.0_amd64.snap\n',
            fake_logger.output)

        self.assertTrue(os.path.exists(self.stage_dir),
                        'Expected a stage directory')

        self.verify_state('part1', self.state_dir, 'prime')

        self.popen_spy.assert_called_once_with([
            'mksquashfs', self.snap_dir, 'snap-test_1.0_amd64.snap',
            '-noappend', '-comp', 'xz', '-no-xattrs', '-all-root'],
            stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
Beispiel #13
0
    def test_snap_renames_stale_snap_build(self, mocked_time):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)
        self.make_snapcraft_yaml()

        mocked_time.return_value = 1234

        snap_build = 'snap-test_1.0_amd64.snap-build'
        with open(snap_build, 'w') as fd:
            fd.write('signed assertion?')

        main(['snap'])

        snap_build_renamed = snap_build + '.1234'
        self.assertEqual([
            'Preparing to pull part1 ',
            'Pulling part1 ',
            'Preparing to build part1 ',
            'Building part1 ',
            'Staging part1 ',
            'Priming part1 ',
            'Renaming stale build assertion to {}'.format(snap_build_renamed),
            'Snapping \'snap-test\' ...',
            'Snapped snap-test_1.0_amd64.snap',
            ], fake_logger.output.splitlines())

        self.assertThat('snap-test_1.0_amd64.snap', FileExists())
        self.assertThat(snap_build, Not(FileExists()))
        self.assertThat(snap_build_renamed, FileExists())
        self.assertThat(
            snap_build_renamed, FileContains('signed assertion?'))
Beispiel #14
0
    def test_snap_from_dir_type_os_does_not_use_all_root(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        meta_dir = os.path.join('mysnap', 'meta')
        os.makedirs(meta_dir)
        with open(os.path.join(meta_dir, 'snap.yaml'), 'w') as f:
            f.write("""name: my_snap
version: 99
architectures: [amd64, armhf]
type: os
""")

        main(['snap', 'mysnap'])

        self.assertEqual(
            'Snapping \'my_snap\' ...\n'
            'Snapped my_snap_99_multi.snap\n',
            fake_logger.output)

        self.popen_spy.assert_called_once_with([
            'mksquashfs', os.path.abspath('mysnap'), 'my_snap_99_multi.snap',
            '-noappend', '-comp', 'xz', '-no-xattrs'],
            stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

        self.assertThat('my_snap_99_multi.snap', FileExists())
Beispiel #15
0
    def test_cleaning_with_strip_does_prime_and_warns(self, mock_clean):
        fake_logger = fixtures.FakeLogger(level=logging.WARNING)
        self.useFixture(fake_logger)

        self.make_snapcraft_yaml(n=3)

        main(['clean', '--step=strip'])

        expected_staged_state = {
            'clean0': states.StageState({'clean0'}, set()),
            'clean1': states.StageState({'clean1'}, set()),
            'clean2': states.StageState({'clean2'}, set()),
        }

        expected_primed_state = {
            'clean0': states.PrimeState({'clean0'}, set()),
            'clean1': states.PrimeState({'clean1'}, set()),
            'clean2': states.PrimeState({'clean2'}, set()),
        }

        self.assertEqual(
            'DEPRECATED: Use `prime` instead of `strip` as '
            'the step to clean\n', fake_logger.output)
        mock_clean.assert_called_with(expected_staged_state,
                                      expected_primed_state, 'prime')
    def test_snap_defaults_with_parts_in_prime(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)
        self.make_snapcraft_yaml()

        # Pretend this part has already been primed
        os.makedirs(self.state_dir)
        open(os.path.join(self.state_dir, 'prime'), 'w').close()

        main(['snap'])

        self.assertEqual(
            'Skipping pull part1 (already ran)\n'
            'Skipping build part1 (already ran)\n'
            'Skipping stage part1 (already ran)\n'
            'Skipping prime part1 (already ran)\n'
            'Snapping \'snap-test\' ...\n'
            'Snapped snap-test_1.0_amd64.snap\n',
            fake_logger.output)

        self.popen_spy.assert_called_once_with([
            'mksquashfs', self.snap_dir, 'snap-test_1.0_amd64.snap',
            '-noappend', '-comp', 'xz', '-no-xattrs', '-all-root'],
            stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

        self.assertThat('snap-test_1.0_amd64.snap', FileExists())
Beispiel #17
0
    def test_init_must_write_snapcraft_yaml(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        expected_yaml = """name: my-snap  # the name of the snap
version: 0  # the version of the snap
summary: This is my-snap's summary  # 79 char long summary
description: This is my-snap's description  # a longer description for the snap
confinement: devmode  # use "strict" to enforce system access only via \
declared interfaces

parts:
    my-part:  # Replace with a part name of your liking
        # Get more information about plugins by running
        # snapcraft help plugins
        # and more information about the available plugins
        # by running
        # snapcraft list-plugins
        plugin: nil"""

        main(['init'])

        self.assertEqual(
            'Created snapcraft.yaml.\nEdit the file to your '
            'liking or run `snapcraft` to get started\n',
            fake_logger.output)

        # Verify the generated yaml
        with open('snapcraft.yaml', 'r') as f:
            self.assertEqual(f.read(), expected_yaml)
    def test_snap_from_dir_type_os_does_not_use_all_root(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        meta_dir = os.path.join('mysnap', 'meta')
        os.makedirs(meta_dir)
        with open(os.path.join(meta_dir, 'snap.yaml'), 'w') as f:
            f.write("""name: my_snap
version: 99
architectures: [amd64, armhf]
type: os
""")

        main(['snap', 'mysnap'])

        self.assertEqual(
            'Snapping \'my_snap\' ...\n'
            'Snapped my_snap_99_multi.snap\n',
            fake_logger.output)

        self.popen_spy.assert_called_once_with([
            'mksquashfs', os.path.abspath('mysnap'), 'my_snap_99_multi.snap',
            '-noappend', '-comp', 'xz', '-no-xattrs'],
            stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

        self.assertThat('my_snap_99_multi.snap', FileExists())
Beispiel #19
0
    def test_sign_build_snapd_failure(
            self, mock_installed, mock_get_snap_data, mock_check_output,
            mock_get_account_info):
        mock_installed.return_value = True
        mock_get_account_info.return_value = {
            'account_id': 'abcd',
            'account_keys': [{'public-key-sha3-384': 'a_hash'}],
            'snaps': {
                '16': {
                    'test-snap': {'snap-id': 'snap-id'},
                }
            }
        }
        mock_get_snap_data.return_value = {
            'name': 'test-snap',
            'grade': 'stable',
        }
        mock_check_output.side_effect = [
            '[{"name": "default", "sha3-384": "a_hash"}]',
            subprocess.CalledProcessError(1, ['a', 'b'])
        ]

        with self.assertRaises(SystemExit) as raised:
            main(['sign-build', self.snap_test.snap_path])

        self.assertEqual(1, raised.exception.code)
        self.assertEqual([
            'Failed to sign build assertion for {}.'.format(
                self.snap_test.snap_path),
            ], self.fake_logger.output.splitlines())

        snap_build_path = self.snap_test.snap_path + '-build'
        self.assertFalse(os.path.exists(snap_build_path))
    def test_snap_with_output(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)
        self.make_snapcraft_yaml()

        main(['snap', '--output', 'mysnap.snap'])

        self.assertEqual(
            'Preparing to pull part1 \n'
            'Pulling part1 \n'
            'Preparing to build part1 \n'
            'Building part1 \n'
            'Staging part1 \n'
            'Priming part1 \n'
            'Snapping \'snap-test\' ...\n'
            'Snapped mysnap.snap\n',
            fake_logger.output)

        self.assertTrue(os.path.exists(self.stage_dir),
                        'Expected a stage directory')

        self.verify_state('part1', self.state_dir, 'prime')

        self.popen_spy.assert_called_once_with([
            'mksquashfs', self.snap_dir, 'mysnap.snap',
            '-noappend', '-comp', 'xz', '-no-xattrs', '-all-root'],
            stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

        self.assertThat('mysnap.snap', FileExists())
Beispiel #21
0
    def test_partial_clean(self):
        parts = self.make_snapcraft_yaml(n=3)

        main(['clean', 'clean0', 'clean2'])

        for i in [0, 2]:
            self.assertFalse(
                os.path.exists(parts[i]['part_dir']),
                'Expected for {!r} to be wiped'.format(parts[i]['part_dir']))

        self.assertTrue(os.path.exists(parts[1]['part_dir']),
                        'Expected a part directory for the clean1 part')

        self.assertTrue(os.path.exists(self.parts_dir))
        self.assertTrue(os.path.exists(self.stage_dir))
        self.assertTrue(os.path.exists(self.prime_dir))

        # Now clean it the rest of the way
        main(['clean', 'clean1'])

        for i in range(0, 3):
            self.assertFalse(
                os.path.exists(parts[i]['part_dir']),
                'Expected for {!r} to be wiped'.format(parts[i]['part_dir']))

        self.assertFalse(os.path.exists(self.parts_dir))
        self.assertFalse(os.path.exists(self.stage_dir))
        self.assertFalse(os.path.exists(self.prime_dir))
    def test_snap_defaults_on_a_tty(self, progress_mock):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)
        self.make_snapcraft_yaml()
        self.isatty_mock.return_value = True

        main(['snap'])

        self.assertEqual(
            'Preparing to pull part1 \n'
            'Pulling part1 \n'
            'Preparing to build part1 \n'
            'Building part1 \n'
            'Staging part1 \n'
            'Priming part1 \n'
            'Snapped snap-test_1.0_amd64.snap\n',
            fake_logger.output)

        self.assertTrue(os.path.exists(self.stage_dir),
                        'Expected a stage directory')

        self.verify_state('part1', self.state_dir, 'prime')

        self.popen_spy.assert_called_once_with([
            'mksquashfs', self.snap_dir, 'snap-test_1.0_amd64.snap',
            '-noappend', '-comp', 'xz', '-no-xattrs', '-all-root'],
            stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

        self.assertThat('snap-test_1.0_amd64.snap', FileExists())
    def test_gated_unknown_snap(self):
        self.client.login('dummy', 'test correct password')

        with self.assertRaises(SystemExit):
            main([self.command_name, 'notfound'])
        self.assertIn("Snap 'notfound' was not found.",
                      self.fake_logger.output)
Beispiel #24
0
    def test_list_plugins_non_tty(self):
        self.maxDiff = None
        fake_terminal = fixture_setup.FakeTerminal(isatty=False)
        self.useFixture(fake_terminal)

        main([self.command_name])
        self.assertEqual(fake_terminal.getvalue(), self.default_plugin_output)
Beispiel #25
0
    def test_no_unicode_in_help_strings(self, mock_stdout):
        helps = ['topics']

        for key in _TOPICS.keys():
            helps.append(str(key))

        # Get a list of plugins
        import snapcraft.plugins
        import os
        from pathlib import Path
        for plugin in Path(snapcraft.plugins.__path__[0]).glob('*.py'):
            if (os.path.isfile(str(plugin)) and
                    not os.path.basename(str(plugin)).startswith('_')):
                helps.append(os.path.basename(str(plugin)[:-3]))

        for key in helps:
            mock_stdout.truncate(0)
            mock_stdout.seek(0)
            with self.subTest(key=key):
                main(['help', key])
                try:
                    mock_stdout.getvalue().encode('ascii')
                except UnicodeEncodeError:
                    self.fail('Non-ASCII characters in help text for '
                              '{!r}'.format(key))
Beispiel #26
0
    def test_list_plugins_large_terminal(self):
        self.maxDiff = None
        fake_terminal = fixture_setup.FakeTerminal(columns=999)
        self.useFixture(fake_terminal)

        main([self.command_name])
        self.assertEqual(fake_terminal.getvalue(), self.default_plugin_output)
Beispiel #27
0
    def test_strip_one_part_only_from_3(self):
        fake_logger = fixtures.FakeLogger(level=logging.ERROR)
        self.useFixture(fake_logger)
        parts = self.make_snapcraft_yaml(n=3)

        main(['strip', 'strip1'])

        self.assertFalse(
            os.path.exists(
                os.path.join(common.get_snapdir(), 'meta', 'snap.yaml')),
            'There should not be a snap.yaml')
        self.assertTrue(os.path.exists(common.get_snapdir()),
                        'Expected a snap directory')
        self.assertTrue(os.path.exists(common.get_stagedir()),
                        'Expected a stage directory')
        self.assertTrue(os.path.exists(common.get_partsdir()),
                        'Expected a parts directory')
        self.assertTrue(os.path.exists(parts[1]['part_dir']),
                        'Expected a part directory for the strip1 part')

        self.verify_state('strip1', parts[1]['state_dir'], 'strip')

        for i in [0, 2]:
            self.assertFalse(os.path.exists(parts[i]['part_dir']),
                             'Pulled wrong part')
            self.assertFalse(os.path.exists(parts[i]['state_dir']),
                             'Expected for only to be a state file for build1')
Beispiel #28
0
    def test_failed_login_with_invalid_credentials(self, mock_login):
        mock_login.side_effect = storeapi.errors.InvalidCredentialsError(
            'error')

        main(['login'])

        self.assertEqual('Login failed.\n', self.fake_logger.output)
    def test_list_plugins_large_terminal(self):
        self.maxDiff = None
        fake_terminal = fixture_setup.FakeTerminal(columns=999)
        self.useFixture(fake_terminal)

        main(['list-plugins'])
        self.assertEqual(fake_terminal.getvalue(), self.default_plugin_output)
Beispiel #30
0
    def test_failed_login_with_store_authentication_error(self, mock_login):
        mock_login.side_effect = storeapi.errors.StoreAuthenticationError(
            'error')

        main(['login'])

        self.assertEqual('Login failed.\n', self.fake_logger.output)
Beispiel #31
0
    def test_partial_clean(self):
        parts = self.make_snapcraft_yaml(n=3)

        main(['clean', 'clean0', 'clean2'])

        for i in [0, 2]:
            self.assertFalse(
                os.path.exists(parts[i]['part_dir']),
                'Expected for {!r} to be wiped'.format(parts[i]['part_dir']))

        self.assertTrue(os.path.exists(parts[1]['part_dir']),
                        'Expected a part directory for the clean1 part')

        self.assertTrue(os.path.exists(self.parts_dir))
        self.assertTrue(os.path.exists(self.stage_dir))
        self.assertTrue(os.path.exists(self.snap_dir))

        # Now clean it the rest of the way
        main(['clean', 'clean1'])

        for i in range(0, 3):
            self.assertFalse(
                os.path.exists(parts[i]['part_dir']),
                'Expected for {!r} to be wiped'.format(parts[i]['part_dir']))

        self.assertFalse(os.path.exists(self.parts_dir))
        self.assertFalse(os.path.exists(self.stage_dir))
        self.assertFalse(os.path.exists(self.snap_dir))
Beispiel #32
0
    def test_push_revision_uses_available_delta(self):
        self.useFixture(fixture_setup.FakeTerminal())
        if self.enable_deltas:
            self.useFixture(fixture_setup.DeltaUploads())

        # Create a source snap
        main(['init'])
        main(['snap'])
        snap_file = glob.glob('*.snap')[0]

        # Upload
        with mock.patch('snapcraft.storeapi.StatusTracker'):
            main(['push', snap_file])

        # create an additional snap, potentially a delta target
        main(['snap'])
        new_snap_file = glob.glob('*.snap')[0]

        # Upload
        with mock.patch('snapcraft.storeapi.StatusTracker'):
            main(['push', new_snap_file])

        _, kwargs = self.mock_upload.call_args
        if self.enable_deltas:
            self.assertEqual(kwargs.get('delta_format'), 'xdelta3')
        else:
            self.assertIsNone(kwargs.get('delta_format'))
Beispiel #33
0
    def test_clean_dependent_parts(self):
        main(['clean', 'dependent', 'nested-dependent'])

        self.assert_clean(['dependent', 'nested-dependent'])
        self.assertTrue(
            os.path.exists(self.part_dirs['main']),
            'Expected part directory for main to be untouched by the clean')
Beispiel #34
0
    def test_push_unregistered_snap_must_raise_exception(self):
        self.useFixture(fixture_setup.FakeTerminal())

        class MockResponse:
            status_code = 404
            error_list = [{
                'code': 'resource-not-found',
                'message': 'Snap not found for name=my-snap-name'
            }]

        patcher = mock.patch.object(storeapi.StoreClient, 'push_precheck')
        mock_precheck = patcher.start()
        self.addCleanup(patcher.stop)
        mock_precheck.side_effect = StorePushError('my-snap-name',
                                                   MockResponse())

        # Create a snap
        main(['init'])
        main(['snap'])
        snap_file = glob.glob('*.snap')[0]

        self.assertRaises(SystemExit, main, ['push', snap_file])

        self.assertIn(
            'You are not the publisher or allowed to push revisions for this '
            'snap. To become the publisher, run `snapcraft register '
            'my-snap-name` and try to push again.', self.fake_logger.output)
Beispiel #35
0
    def test_sign_build_no_usable_keys(
            self, mock_installed, mock_get_snap_data, mock_check_output,
            mock_get_account_info):
        mock_installed.return_value = True
        mock_get_account_info.return_value = {
            'account_id': 'abcd',
            'snaps': {
                '16': {
                    'test-snap': {'snap-id': 'snap-id'},
                }
            }
        }
        mock_get_snap_data.return_value = {
            'name': 'test-snap',
            'grade': 'stable',
        }
        mock_check_output.side_effect = [
            '[]',
        ]

        with self.assertRaises(SystemExit) as raised:
            main(['sign-build', self.snap_test.snap_path])

        self.assertEqual(1, raised.exception.code)
        self.assertEqual([
            'You have no usable keys.',
            'Please create at least one key with `snapcraft create-key` '
            'for use with snap.',
            ], self.fake_logger.output.splitlines())

        snap_build_path = self.snap_test.snap_path + '-build'
        self.assertFalse(os.path.exists(snap_build_path))
 def test_list_plugins_error_invalid_terminal_size(self, mock_subprocess,
                                                   mock_stdout):
     def raise_error(cmd, stderr):
         raise OSError()
     mock_subprocess.side_effect = raise_error
     main(['list-plugins'])
     self.assertEqual(mock_stdout.getvalue(), self.default_plugin_output)
Beispiel #37
0
    def test_sign_build_unregistered_key(
            self, mock_installed, mock_get_snap_data, mock_check_output,
            mock_get_account_info):
        mock_installed.return_value = True
        mock_get_account_info.return_value = {
            'account_id': 'abcd',
            'account_keys': [{'public-key-sha3-384': 'another_hash'}],
            'snaps': {
                '16': {
                    'test-snap': {'snap-id': 'snap-id'},
                }
            }
        }
        mock_get_snap_data.return_value = {
            'name': 'test-snap',
            'grade': 'stable',
        }
        mock_check_output.side_effect = [
            '[{"name": "default", "sha3-384": "a_hash"}]',
        ]

        with self.assertRaises(SystemExit) as raised:
            main(['sign-build', self.snap_test.snap_path])

        self.assertEqual(1, raised.exception.code)
        self.assertEqual([
            'The key \'default\' is not registered in the Store.',
            'Please register it with `snapcraft register-key \'default\'` '
            'before signing and pushing signatures to the Store.',
        ], self.fake_logger.output.splitlines())
        snap_build_path = self.snap_test.snap_path + '-build'
        self.assertFalse(os.path.exists(snap_build_path))
 def test_list_plugins_error_invalid_subprocess_call(self, mock_subprocess,
                                                     mock_stdout):
     def raise_error(cmd, stderr):
         raise subprocess.CalledProcessError(returncode=1, cmd=cmd)
     mock_subprocess.side_effect = raise_error
     main(['list-plugins'])
     self.assertEqual(mock_stdout.getvalue(), self.default_plugin_output)
Beispiel #39
0
    def test_sign_build_push_successfully(
            self, mock_installed, mock_get_snap_data, mock_check_output,
            mock_get_account_info, mock_push_snap_build):
        mock_installed.return_value = True
        mock_get_account_info.return_value = {
            'account_id': 'abcd',
            'account_keys': [{'public-key-sha3-384': 'a_hash'}],
            'snaps': {
                '16': {
                    'test-snap': {'snap-id': 'snap-id'},
                }
            }
        }
        mock_get_snap_data.return_value = {
            'name': 'test-snap',
            'grade': 'stable',
        }
        mock_check_output.side_effect = [
            '[{"name": "default", "sha3-384": "a_hash"}]',
            b'Mocked assertion'
        ]

        main(['sign-build', self.snap_test.snap_path])

        snap_build_path = self.snap_test.snap_path + '-build'
        self.assertTrue(os.path.exists(snap_build_path))
        self.assertEqual([
            'Build assertion {} saved to disk.'.format(snap_build_path),
            'Build assertion {} pushed to the Store.'.format(snap_build_path),
        ], self.fake_logger.output.splitlines())
        mock_check_output.assert_called_with([
            'snap', 'sign-build', '--developer-id=abcd', '--snap-id=snap-id',
            '--grade=stable', '-k', 'default', self.snap_test.snap_path,
        ])
        mock_push_snap_build.assert_called_with('snap-id', 'Mocked assertion')
Beispiel #40
0
    def test_prime_one_part_only_from_3(self):
        fake_logger = fixtures.FakeLogger(level=logging.ERROR)
        self.useFixture(fake_logger)
        parts = self.make_snapcraft_yaml(n=3)

        main(['prime', 'prime1'])

        self.assertFalse(
            os.path.exists(os.path.join(self.snap_dir, 'meta', 'snap.yaml')),
            'There should not be a snap.yaml')
        self.assertTrue(os.path.exists(self.snap_dir),
                        'Expected a prime directory')
        self.assertTrue(os.path.exists(self.stage_dir),
                        'Expected a stage directory')
        self.assertTrue(os.path.exists(self.parts_dir),
                        'Expected a parts directory')
        self.assertTrue(os.path.exists(parts[1]['part_dir']),
                        'Expected a part directory for the prime1 part')

        self.verify_state('prime1', parts[1]['state_dir'], 'prime')

        for i in [0, 2]:
            self.assertFalse(os.path.exists(parts[i]['part_dir']),
                             'Pulled wrong part')
            self.assertFalse(
                os.path.exists(parts[i]['state_dir']),
                'Expected for only to be a state file for build1')
Beispiel #41
0
    def test_stage_ran_twice_is_a_noop(self):
        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)
        parts = self.make_snapcraft_yaml()

        main(['stage'])

        self.assertEqual(
            'Preparing to pull stage0 \n'
            'Pulling stage0 \n'
            'Preparing to build stage0 \n'
            'Building stage0 \n'
            'Staging stage0 \n', fake_logger.output)

        self.assertTrue(os.path.exists(self.stage_dir),
                        'Expected a stage directory')
        self.assertTrue(os.path.exists(self.parts_dir),
                        'Expected a parts directory')
        self.assertTrue(os.path.exists(parts[0]['part_dir']),
                        'Expected a part directory for the build0 part')

        self.verify_state('build0', parts[0]['state_dir'], 'stage')

        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        main(['stage'])

        self.assertEqual(
            'Skipping pull stage0 (already ran)\n'
            'Skipping build stage0 (already ran)\n'
            'Skipping stage stage0 (already ran)\n', fake_logger.output)
    def test_upload_existing_snap(self):
        patcher = mock.patch('snapcraft.storeapi.upload')
        mock_upload = patcher.start()
        self.addCleanup(patcher.stop)

        patcher = mock.patch('snapcraft._store.load_config')
        mock_load_config = patcher.start()
        self.addCleanup(patcher.stop)
        mock_load_config.return_value = 'test config'

        patcher = mock.patch('subprocess.check_call')
        mock_check_call = patcher.start()
        self.addCleanup(patcher.stop)

        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        open('test.snap', 'w').close()

        self._patch_snap_yaml('snaptestname')
        main(['upload', 'test.snap'])

        mock_check_call.assert_called_once_with([
            'unsquashfs', '-d',
            os.path.join(os.getcwd(), 'squashfs-root'), 'test.snap', '-e',
            os.path.join('meta', 'snap.yaml')
        ])
        self.assertEqual('Uploading existing test.snap.\n', fake_logger.output)

        mock_upload.assert_called_once_with('test.snap',
                                            'snaptestname',
                                            config='test config')
Beispiel #43
0
    def test_clean_dependent_parts(self):
        main(['clean', 'dependent', 'nested-dependent'])

        self.assert_clean(['dependent', 'nested-dependent'])
        self.assertTrue(
            os.path.exists(self.part_dirs['main']),
            'Expected part directory for main to be untouched by the clean')
Beispiel #44
0
    def test_close_basic(self, mock_close_channels, mock_get_account_info):
        mock_get_account_info.return_value = {
            'snaps': {
                '16': {'basic': {'snap-id': 'snap-id'}}
            }
        }
        closed_channels = ['beta']
        channel_map_tree = {
            'latest': {
                '16': {
                    'amd64': [
                        {'channel': 'stable', 'info': 'none'},
                        {'channel': 'candidate', 'info': 'none'},
                        {'channel': 'beta', 'info': 'specific',
                         'version': '1.1', 'revision': 42},
                        {'channel': 'edge', 'info': 'tracking'}
                    ],
                }
            }
        }
        mock_close_channels.side_effect = [
            (closed_channels, channel_map_tree),
        ]

        main(['close', 'basic', 'beta'])

        self.assertEqual([
            'Track    Arch    Channel    Version    Revision',
            'latest   amd64   stable     -          -',
            '                 candidate  -          -',
            '                 beta       1.1        42',
            '                 edge       ^          ^',
            '',
            '\x1b[0;32mThe beta channel is now closed.\x1b[0m'
        ], self.fake_terminal.getvalue().splitlines())
Beispiel #45
0
    def test_print_topics(self):
        main(['help', 'topics'])

        output = self.fake_terminal.getvalue().strip().split('\n')
        for t in _TOPICS:
            self.assertTrue(
                t in output, 'Missing topic: {!r} in {!r}'.format(t, output))
Beispiel #46
0
    def test_upload_existing_snap(self):
        patcher = mock.patch('snapcraft.storeapi.upload')
        mock_upload = patcher.start()
        self.addCleanup(patcher.stop)

        patcher = mock.patch('snapcraft._store.load_config')
        mock_load_config = patcher.start()
        self.addCleanup(patcher.stop)
        mock_load_config.return_value = 'test config'

        patcher = mock.patch('subprocess.check_call')
        mock_check_call = patcher.start()
        self.addCleanup(patcher.stop)

        fake_logger = fixtures.FakeLogger(level=logging.INFO)
        self.useFixture(fake_logger)

        open('test.snap', 'w').close()

        self._patch_snap_yaml('snaptestname')
        main(['upload', 'test.snap'])

        mock_check_call.assert_called_once_with(
            ['unsquashfs', '-d', os.path.join(os.getcwd(), 'squashfs-root'),
             'test.snap', '-e', os.path.join('meta', 'snap.yaml')])
        self.assertEqual(
            'Uploading existing test.snap.\n', fake_logger.output)

        mock_upload.assert_called_once_with(
            'test.snap',
            'snaptestname',
            config='test config')
    def test_gated_no_validations(self):
        self.client.login('dummy', 'test correct password')

        main([self.command_name, 'basic'])

        expected_output = "There are no validations for snap 'basic'\n"
        self.assertEqual(expected_output, self.fake_terminal.getvalue())
Beispiel #48
0
    def test_register_key_successfully(self, mock_installed, mock_input,
                                       mock_getpass, mock_check_output,
                                       mock_login,
                                       mock_get_account_information,
                                       mock_register_key):
        mock_installed.return_value = True
        mock_input.side_effect = ['*****@*****.**', '123456']
        mock_getpass.return_value = 'secret'
        mock_check_output.side_effect = mock_snap_output
        mock_login.side_effect = [
            storeapi.errors.StoreTwoFactorAuthenticationRequired(), None]
        mock_get_account_information.return_value = {'account_id': 'abcd'}

        main(['register-key', 'default'])

        self.assertEqual(
            'Login successful.\n'
            'Registering key ...\n'
            'Done. The key "default" ({}) may be used to sign your '
            'assertions.\n'.format(get_sample_key('default')['sha3-384']),
            self.fake_logger.output)

        mock_login.assert_called_with(
            '*****@*****.**', 'secret',
            one_time_password='******', acls=['modify_account_key'],
            packages=None, channels=None, save=False)
        self.assertEqual(1, mock_register_key.call_count)
        expected_assertion = dedent('''\
            type: account-key-request
            account-id: abcd
            name: default
            public-key-sha3-384: {}
            ''').format(get_sample_key('default')['sha3-384'])
        mock_register_key.assert_called_once_with(expected_assertion)
    def test_register_key_successfully(self, mock_installed, mock_input,
                                       mock_getpass, mock_check_output,
                                       mock_login,
                                       mock_get_account_information,
                                       mock_register_key):
        mock_installed.return_value = True
        mock_input.side_effect = ['*****@*****.**', '123456']
        mock_getpass.return_value = 'secret'
        mock_check_output.side_effect = mock_snap_output
        mock_get_account_information.return_value = {'account_id': 'abcd'}

        main(['register-key', 'default'])

        self.assertEqual(
            'Authenticating against Ubuntu One SSO.\n'
            'Login successful.\n'
            'Registering key ...\n'
            'Done. The key "default" ({}) may be used to sign your '
            'assertions.\n'.format(get_sample_key('default')['sha3-384']),
            self.fake_logger.output)

        mock_login.assert_called_once_with('*****@*****.**',
                                           'secret',
                                           one_time_password='******',
                                           acls=['modify_account_key'],
                                           save=False)
        self.assertEqual(1, mock_register_key.call_count)
        expected_assertion = dedent('''\
            type: account-key-request
            account-id: abcd
            name: default
            public-key-sha3-384: {}
            ''').format(get_sample_key('default')['sha3-384'])
        mock_register_key.assert_called_once_with(expected_assertion)
Beispiel #50
0
    def test_partial_clean(self):
        parts = self.make_snapcraft_yaml(n=3)

        main(["clean", "clean0", "clean2"])

        for i in [0, 2]:
            self.assertFalse(
                os.path.exists(parts[i]["part_dir"]), "Expected for {!r} to be wiped".format(parts[i]["part_dir"])
            )

        self.assertTrue(os.path.exists(parts[1]["part_dir"]), "Expected a part directory for the clean1 part")

        self.assertTrue(os.path.exists(self.parts_dir))
        self.assertTrue(os.path.exists(self.stage_dir))
        self.assertTrue(os.path.exists(self.snap_dir))

        # Now clean it the rest of the way
        main(["clean", "clean1"])

        for i in range(0, 3):
            self.assertFalse(
                os.path.exists(parts[i]["part_dir"]), "Expected for {!r} to be wiped".format(parts[i]["part_dir"])
            )

        self.assertFalse(os.path.exists(self.parts_dir))
        self.assertFalse(os.path.exists(self.stage_dir))
        self.assertFalse(os.path.exists(self.snap_dir))