Skip to content

Commit c885bf8

Browse files
committed
feat(controller): add STACK support
1 parent a33cde6 commit c885bf8

15 files changed

Lines changed: 142 additions & 59 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ commit-hook:
4343
cp _scripts/util/commit-msg .git/hooks/commit-msg
4444

4545
full-clean: check-docker
46-
docker images -q $(IMAGE_PREFIX)$(COMPONENT) | xargs docker rmi -f
46+
docker images -q $(IMAGE_PREFIX)/$(COMPONENT) | xargs docker rmi -f
4747

4848
test: test-style test-unit test-functional
4949

charts/controller/templates/controller-deployment.yaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,6 @@ spec:
7373
value: "{{ .Values.global.registry_location }}"
7474
- name: "DRYCC_REGISTRY_SECRET_PREFIX"
7575
value: "{{ .Values.global.secret_prefix }}"
76-
- name: "SLUGRUNNER_IMAGE_NAME"
77-
valueFrom:
78-
configMapKeyRef:
79-
name: slugrunner-config
80-
key: image
8176
- name: "IMAGE_PULL_POLICY"
8277
value: "{{ .Values.app_pull_policy }}"
8378
- name: "TZ"
@@ -137,7 +132,13 @@ spec:
137132
volumeMounts:
138133
- mountPath: /var/run/docker.sock
139134
name: docker-socket
135+
- mountPath: /etc/slugbuilder
136+
name: slugrunner-config
137+
readOnly: true
140138
volumes:
141139
- name: docker-socket
142140
hostPath:
143141
path: /var/run/docker.sock
142+
- name: slugrunner-config
143+
configMap:
144+
name: slugrunner-config
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11.20 on 2019-04-02 01:57
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('api', '0029_tls_certs_auto_enabled'),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name='build',
17+
name='stack',
18+
field=models.CharField(max_length=32),
19+
),
20+
]

rootfs/api/models/app.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,11 @@ def _scale_pods(self, scale_types):
497497
app_settings = self.appsettings_set.latest()
498498

499499
# use slugrunner image for app if buildpack app otherwise use normal image
500-
image = settings.SLUGRUNNER_IMAGE if release.build.type == 'buildpack' else release.image
500+
if release.build.type == 'buildpack':
501+
image = next(filter(lambda item: item['name'] == release.build.stack,
502+
settings.SLUGRUNNER_IMAGES))['image']
503+
else:
504+
image = release.image
501505

502506
tasks = []
503507
for scale_type, replicas in scale_types.items():
@@ -582,7 +586,11 @@ def deploy(self, release, force_deploy=False, rollback_on_failure=True): # noqa
582586
self._check_deployment_in_progress(deploys, force_deploy)
583587

584588
# use slugrunner image for app if buildpack app otherwise use normal image
585-
image = settings.SLUGRUNNER_IMAGE if release.build.type == 'buildpack' else release.image
589+
if release.build.type == 'buildpack':
590+
image = next(filter(lambda item: item['name'] == release.build.stack,
591+
settings.SLUGRUNNER_IMAGES))['image']
592+
else:
593+
image = release.image
586594

587595
try:
588596
# create the application config in k8s (secret in this case) for all deploy objects
@@ -809,7 +817,11 @@ def pod_name(size=5, chars=string.ascii_lowercase + string.digits):
809817

810818
app_settings = self.appsettings_set.latest()
811819
# use slugrunner image for app if buildpack app otherwise use normal image
812-
image = settings.SLUGRUNNER_IMAGE if release.build.type == 'buildpack' else release.image
820+
if release.build.type == 'buildpack':
821+
image = next(filter(lambda item: item['name'] == release.build.stack,
822+
settings.SLUGRUNNER_IMAGES))['image']
823+
else:
824+
image = release.image
813825

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

rootfs/api/models/build.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Build(UuidAuditedModel):
1717
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
1818
app = models.ForeignKey('App', on_delete=models.CASCADE)
1919
image = models.TextField()
20+
stack = models.CharField(max_length=32)
2021

2122
# optional fields populated by builder
2223
sha = models.CharField(max_length=40, blank=True)

rootfs/api/serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ class BuildSerializer(serializers.ModelSerializer):
192192
class Meta:
193193
"""Metadata options for a :class:`BuildSerializer`."""
194194
model = models.Build
195-
fields = ['owner', 'app', 'image', 'sha', 'procfile', 'dockerfile', 'created',
196-
'updated', 'uuid']
195+
fields = ['owner', 'app', 'image', 'stack', 'sha', 'procfile',
196+
'dockerfile', 'created', 'updated', 'uuid']
197197

198198
def validate_procfile(self, data):
199199
for key, value in data.items():

rootfs/api/settings/production.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import os.path
66
import tempfile
77
import ldap
8+
import json
89

910
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
1011

@@ -266,7 +267,20 @@
266267
PLATFORM_DOMAIN = os.environ.get('DRYCC_PLATFORM_DOMAIN', 'local.drycc.cc')
267268

268269
# k8s image policies
269-
SLUGRUNNER_IMAGE = os.environ.get('SLUGRUNNER_IMAGE_NAME', 'quay.io/drycc/slugrunner:canary') # noqa
270+
if os.path.exists('/etc/slugrunner/images.json'):
271+
with open('/etc/slugrunner/images.json') as fb:
272+
SLUGRUNNER_IMAGES = json.load(fb)
273+
else:
274+
SLUGRUNNER_IMAGES = [
275+
{
276+
"name": 'heroku-18',
277+
"image": 'drycc/slugrunner:canary.heroku-18',
278+
},
279+
{
280+
"name": 'heroku-16',
281+
"image": 'drycc/slugrunner:canary.heroku-16',
282+
},
283+
]
270284
IMAGE_PULL_POLICY = os.environ.get('IMAGE_PULL_POLICY', "IfNotPresent") # noqa
271285

272286
# True, true, yes, y and more evaluate to True

rootfs/api/tests/test_app.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ def test_run(self, mock_requests):
290290
app_id = self.create_app()
291291

292292
# create build
293-
body = {'image': 'autotest/example'}
293+
body = {'image': 'autotest/example', 'stack': 'container'}
294294
url = '/v2/apps/{app_id}/builds'.format(**locals())
295295
response = self.client.post(url, body)
296296
self.assertEqual(response.status_code, 201, response.data)
@@ -313,7 +313,7 @@ def test_run_failure(self, mock_requests):
313313
app_id = self.create_app()
314314

315315
# create build
316-
body = {'image': 'autotest/example'}
316+
body = {'image': 'autotest/example', 'stack': 'container'}
317317
url = '/v2/apps/{app_id}/builds'.format(**locals())
318318
response = self.client.post(url, body)
319319
self.assertEqual(response.status_code, 201, response.data)
@@ -507,7 +507,7 @@ def test_app_verify_application_health_success(self, mock_requests):
507507

508508
# deploy app to get verification
509509
url = "/v2/apps/{}/builds".format(app_id)
510-
body = {'image': 'autotest/example'}
510+
body = {'image': 'autotest/example', 'stack': 'container'}
511511
response = self.client.post(url, body)
512512
self.assertEqual(response.status_code, 201, response.data)
513513
self.assertEqual(response.data['image'], body['image'])
@@ -541,7 +541,7 @@ def test_app_verify_application_health_failure_404(self, mock_requests):
541541

542542
# deploy app to get verification
543543
url = "/v2/apps/{}/builds".format(app_id)
544-
body = {'image': 'autotest/example'}
544+
body = {'image': 'autotest/example', 'stack': 'container'}
545545
response = self.client.post(url, body)
546546
self.assertEqual(response.status_code, 201, response.data)
547547
self.assertEqual(response.data['image'], body['image'])
@@ -566,7 +566,7 @@ def _raise_exception(request, ctx):
566566

567567
# deploy app to get verification
568568
url = "/v2/apps/{}/builds".format(app_id)
569-
body = {'image': 'autotest/example'}
569+
body = {'image': 'autotest/example', 'stack': 'container'}
570570
response = self.client.post(url, body)
571571
self.assertEqual(response.status_code, 201, response.data)
572572
self.assertEqual(response.data['image'], body['image'])
@@ -659,7 +659,7 @@ def test_build_env_vars(self, mock_requests):
659659
# Make sure an exception is raised when calling without a build available
660660
with self.assertRaises(DryccException):
661661
app._build_env_vars(app.release_set.latest())
662-
data = {'image': 'autotest/example'}
662+
data = {'image': 'autotest/example', 'stack': 'heroku-18'}
663663
url = "/v2/apps/{app.id}/builds".format(**locals())
664664
response = self.client.post(url, data)
665665
self.assertEqual(response.status_code, 201, response.data)
@@ -697,7 +697,7 @@ def test_build_env_vars(self, mock_requests):
697697
def test_gather_app_settings(self, mock_requests):
698698
app = App.objects.create(owner=self.user)
699699
app.save()
700-
data = {'image': 'autotest/example'}
700+
data = {'image': 'autotest/example', 'stack': 'container'}
701701
url = "/v2/apps/{app.id}/builds".format(**locals())
702702
response = self.client.post(url, data)
703703
self.assertEqual(response.status_code, 201, response.data)
@@ -734,7 +734,7 @@ def test_app_name_bad_regex(self, mock_requests):
734734

735735
# deploy to an app that doesn't exist should fail with 404
736736
url = "/v2/apps/{}/builds".format('={}'.format(app_id))
737-
body = {'image': 'autotest/example'}
737+
body = {'image': 'autotest/example', 'stack': 'container'}
738738
response = self.client.post(url, body)
739739
self.assertEqual(response.status_code, 404, response)
740740

0 commit comments

Comments
 (0)