Skip to content
This repository has been archived by the owner on May 6, 2020. It is now read-only.

feat(api): Allow using an unreleased image for the run command #1208

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions rootfs/api/models/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ def logs(self, log_lines=str(settings.LOG_LINES)):
# cast content to string since it comes as bytes via the requests object
return str(r.content.decode('utf-8'))

def run(self, user, command):
def run(self, user, command, image=None):
def pod_name(size=5, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))

Expand All @@ -695,7 +695,11 @@ def pod_name(size=5, chars=string.ascii_lowercase + string.digits):

app_settings = self.appsettings_set.latest()
# use slugrunner image for app if buildpack app otherwise use normal image
image = settings.SLUGRUNNER_IMAGE if release.build.type == 'buildpack' else release.image
if image is None:
if release.build.type == 'buildpack':
image = settings.SLUGRUNNER_IMAGE
else:
image = release.image

data = self._gather_app_settings(release, app_settings, process_type='run', replicas=1)

Expand Down
22 changes: 22 additions & 0 deletions rootfs/api/tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,28 @@ def test_run(self, mock_requests):
self.assertEqual(response.data['exit_code'], 0)
self.assertEqual(response.data['output'], 'mock')

@mock.patch('api.models.App.deploy', mock_none)
@mock.patch('api.models.Release.publish', mock_none)
def test_run_with_undeployed_image(self, mock_requests):
"""
A user should be able to run a one off command with an undeployed image
"""
app_id = self.create_app()

# create build
body = {'image': 'autotest/example'}
url = '/v2/apps/{app_id}/builds'.format(**locals())
response = self.client.post(url, body)
self.assertEqual(response.status_code, 201, response.data)

# run command
with mock.patch('scheduler.KubeHTTPClient.run') as kube_run:
url = '/v2/apps/{}/run'.format(app_id)
image = 'autotest/example:canary'
body = {'image': image, 'command': 'ls -al'}
response = self.client.post(url, body)
self.assertEqual(image, kube_run.call_args[0][2])

def test_run_failure(self, mock_requests):
"""Raise a KubeException via scheduler.run"""
app_id = self.create_app()
Expand Down
4 changes: 3 additions & 1 deletion rootfs/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,9 @@ def run(self, request, **kwargs):
app = self.get_object()
if not request.data.get('command'):
raise DeisException("command is a required field")
rc, output = app.run(self.request.user, request.data['command'])
rc, output = app.run(self.request.user,
request.data['command'],
image=request.data.get('image'))
return Response({'exit_code': rc, 'output': str(output)})

def update(self, request, **kwargs):
Expand Down