Skip to content

Commit

Permalink
Add snaps as a part source, from local file, from URL and from the store
Browse files Browse the repository at this point in the history
  • Loading branch information
mhall119 committed Jan 20, 2017
1 parent 6e0005e commit 0506c59
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
Binary file added demos/tomcat-snap/sample.war
Binary file not shown.
26 changes: 26 additions & 0 deletions demos/tomcat-snap/snapcraft.yaml
@@ -0,0 +1,26 @@
name: snap-part-demo
version: 1.0
summary: Demo using a snap part
description: This is a demo snap using Tomcat from another snap
confinement: strict
grade: devel

apps:
tomcat:
command: run.sh
daemon: simple
plugs: [network-bind]

parts:
tomcat:
plugin: dump
source: tomcat_8.5.5_amd64.snap
webapp:
plugin: dump
source: .
organize:
sample.war: webapps/sample.war
stage:
- webapps/sample.war
prime:
- webapps/sample.war
4 changes: 4 additions & 0 deletions snapcraft/internal/sources/__init__.py
Expand Up @@ -84,6 +84,7 @@
from ._subversion import Subversion # noqa
from ._tar import Tar # noqa
from ._zip import Zip # noqa
from ._snap import Snap # noqa

logging.getLogger('urllib3').setLevel(logging.CRITICAL)

Expand Down Expand Up @@ -134,6 +135,7 @@ def get(sourcedir, builddir, options):
'svn': Subversion,
'tar': Tar,
'zip': Zip,
'snap': Snap,
}


Expand Down Expand Up @@ -164,6 +166,8 @@ def _get_source_type_from_uri(source, ignore_errors=False):
source_type = 'deb'
elif source.endswith('rpm'):
source_type = 'rpm'
elif source.endswith('.snap'):
source_type = 'snap'
elif common.isurl(source) and not ignore_errors:
raise ValueError('no handler to manage source ({})'.format(source))
elif not os.path.isdir(source) and not ignore_errors:
Expand Down
84 changes: 84 additions & 0 deletions snapcraft/internal/sources/_snap.py
@@ -0,0 +1,84 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright (C) 2015, 2016 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import debian.debfile
import os
import shutil
import tempfile
import logging
import snapcraft
import subprocess

from . import errors
from ._base import FileBase

logger = logging.getLogger(__name__)

class Snap(FileBase):

def __init__(self, source, source_dir, source_tag=None, source_commit=None,
source_branch=None, source_depth=None):
super().__init__(source, source_dir, source_tag, source_commit,
source_branch, source_depth)
if source_commit:
raise errors.IncompatibleOptionsError(
'can\'t specify a source-commit for a snap source')
self.source_channel = self.source_branch or 'stable'
self.snap_file = self.source

def pull(self):
logger.info("Pulling snap: %s" % self.source)
if self.source.endswith('.snap'):
super().pull()
self.snap_file = os.path.join(self.source_dir, self.source)
else:
self.snap_file = os.path.join(self.source_dir, '%s.snap' % self.source)
self._download()
self.provision(self.source_dir)

def _download(self):
logger.info("Downloading snap: %s" % self.snap_file)

store = snapcraft.storeapi.StoreClient()
try:
arch = snapcraft.ProjectOptions().deb_arch
package = store.cpi.get_package(self.source, self.source_channel, arch)
store._download_snap(
self.source, self.source_channel, arch, self.snap_file,
package['anon_download_url'], package['download_sha512'])
except snapcraft.storeapi.errors.SHAMismatchError:
raise RuntimeError(
'Failed to download {} at {} (mismatched SHA)'.format(
self.source, self.source_dir))

def provision(self, dst, clean_target=True, keep_snap=False):
logger.info("Provisioning snap: %s to %s" % (self.snap_file, dst))

# Extract the source snap
output = subprocess.check_output(['unsquashfs', '-d', dst, '-f', self.snap_file])

# We don't want a part's snap.yaml conflicting with the parent snap's
snap_meta = os.path.join(dst, 'meta', 'snap.yaml')
if os.path.exists(snap_meta):
os.remove(snap_meta)

# Remove any previously generated snap command wrappers
for cmd_file in os.listdir(dst):
if cmd_file.startswith('command-') and cmd_file.endswith('.wrapper'):
os.remove(os.path.join(dst, cmd_file))

if not keep_snap:
os.remove(os.path.join(dst, os.path.basename(self.snap_file)))

0 comments on commit 0506c59

Please sign in to comment.