Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2371)

Unified Diff: appengine/swarming/server/task_request.py

Issue 1946253003: swarming: refactor cipd input (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@default-isolate-server
Patch Set: rebased Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « appengine/swarming/server/config_test.py ('k') | appengine/swarming/server/task_request_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: appengine/swarming/server/task_request.py
diff --git a/appengine/swarming/server/task_request.py b/appengine/swarming/server/task_request.py
index dc7eca1c68c1d8d6706aca36dfd1c8b10d880803..2d2a2aeb557c3fa311f2a002754b0f26a6d40b36 100644
--- a/appengine/swarming/server/task_request.py
+++ b/appengine/swarming/server/task_request.py
@@ -48,7 +48,6 @@ separate entity to clearly declare the boundary for task request deduplication.
import datetime
import hashlib
-import logging
import random
import re
import urlparse
@@ -60,6 +59,8 @@ from components import auth
from components import datastore_utils
from components import pubsub
from components import utils
+
+from server import config
from server import task_pack
import cipd
@@ -94,7 +95,6 @@ _BEGINING_OF_THE_WORLD = datetime.datetime(2010, 1, 1, 0, 0, 0, 0)
# Used for isolated files.
_HASH_CHARS = frozenset('0123456789abcdef')
-NAMESPACE_RE = re.compile(r'^[a-z0-9A-Z\-._]+$')
### Properties validators must come before the models.
@@ -107,7 +107,7 @@ def _validate_isolated(prop, value):
'%s must be lowercase hex of length 40, not %s' % (prop._name, value))
-def _validate_hostname(prop, value):
+def _validate_url(prop, value):
# pylint: disable=unused-argument
if value:
# It must be https://*.appspot.com or https?://*
@@ -125,7 +125,7 @@ def _validate_hostname(prop, value):
def _validate_namespace(prop, value):
- if not NAMESPACE_RE.match(value):
+ if not config.NAMESPACE_RE.match(value):
raise datastore_errors.BadValueError('malformed %s' % prop._name)
@@ -204,18 +204,19 @@ def _validate_tags(prop, value):
'%s must be key:value form, not %s' % (prop._name, value))
-def _validate_package_name(prop, value):
- """Validates a CIPD package name."""
- if not cipd.is_valid_package_name(value):
+def _validate_package_name_template(prop, value):
+ """Validates a CIPD package name template."""
+ if not cipd.is_valid_package_name_template(value):
raise datastore_errors.BadValueError(
- '%s must be a valid CIPD package name "%s"' % (prop._name, value))
+ '%s must be a valid CIPD package name template "%s"' % (
+ prop._name, value))
def _validate_package_version(prop, value):
"""Validates a CIPD package version."""
if not cipd.is_valid_version(value):
raise datastore_errors.BadValueError(
- '%s must be a valid package version "%s"' % (prop._name, value))
+ '%s must be a valid package version "%s"' % (prop._name, value))
### Models.
@@ -233,7 +234,7 @@ class FilesRef(ndb.Model):
isolated = ndb.StringProperty(validator=_validate_isolated, indexed=False)
# The hostname of the isolated server to use.
isolatedserver = ndb.StringProperty(
- validator=_validate_hostname, indexed=False)
+ validator=_validate_url, indexed=False)
# Namespace on the isolate server.
namespace = ndb.StringProperty(validator=_validate_namespace, indexed=False)
@@ -249,8 +250,12 @@ class CipdPackage(ndb.Model):
A part of TaskProperties.
"""
+ # Package name template. May use cipd.ALL_PARAMS.
+ # Most users will specify ${platform} parameter.
package_name = ndb.StringProperty(
- indexed=False, validator=_validate_package_name)
+ indexed=False, validator=_validate_package_name_template)
+ # Package version that is valid for all packages matched by package_name.
+ # Most users will specify tags.
version = ndb.StringProperty(
indexed=False, validator=_validate_package_version)
@@ -262,6 +267,42 @@ class CipdPackage(ndb.Model):
raise datastore_errors.BadValueError('CIPD package version is required')
+class CipdInput(ndb.Model):
+ """Specifies which CIPD client and packages to install, from which server.
+
+ A part of TaskProperties.
+ """
+ # URL of the CIPD server. Must start with "https://" or "http://".
+ server = ndb.StringProperty(indexed=False, validator=_validate_url)
+
+ # CIPD package of CIPD client to use.
+ # client_package.version is required.
+ client_package = ndb.LocalStructuredProperty(CipdPackage)
+
+ # List of packages to install in $CIPD_PATH prior task execution.
+ packages = ndb.LocalStructuredProperty(CipdPackage, repeated=True)
+
+ def _pre_put_hook(self):
+ if not self.server:
+ raise datastore_errors.BadValueError('cipd server is required')
+ if not self.client_package:
+ raise datastore_errors.BadValueError('client_package is required')
+ self.client_package._pre_put_hook()
+
+ if not self.packages:
+ raise datastore_errors.BadValueError(
+ 'cipd_input cannot have an empty package list')
+
+ package_names = set()
+ for p in self.packages:
+ p._pre_put_hook()
+ if p.package_name in package_names:
+ raise datastore_errors.BadValueError(
+ 'package %s is specified more than once' % p.package_name)
+ package_names.add(p.package_name)
+ self.packages.sort(key=lambda p: p.package_name)
+
+
class TaskProperties(ndb.Model):
"""Defines all the properties of a task to be run on the Swarming
infrastructure.
@@ -303,9 +344,8 @@ class TaskProperties(ndb.Model):
# Only inputs_ref.isolated or command can be specified.
inputs_ref = ndb.LocalStructuredProperty(FilesRef)
- # A list of CIPD packages to install $CIPD_PATH and $PATH before task
- # execution.
- packages = ndb.LocalStructuredProperty(CipdPackage, repeated=True)
+ # CIPD packages to install.
+ cipd_input = ndb.LocalStructuredProperty(CipdInput)
# Filter to use to determine the required properties on the bot to run on. For
# example, Windows or hostname. Encoded as json. Optional but highly
@@ -392,22 +432,15 @@ class TaskProperties(ndb.Model):
if self.inputs_ref:
self.inputs_ref._pre_put_hook()
- package_names = set()
- for p in self.packages:
- p._pre_put_hook()
- if p.package_name in package_names:
- raise datastore_errors.BadValueError(
- 'package %s is specified more than once' % p.package_name)
- package_names.add(p.package_name)
- self.packages.sort(key=lambda p: p.package_name)
-
- if self.idempotent:
- pinned = lambda p: cipd.is_pinned_version(p.version)
- if self.packages and any(not pinned(p) for p in self.packages):
- raise datastore_errors.BadValueError(
- 'an idempotent task cannot have unpinned packages; '
- 'use instance IDs or tags as package versions')
-
+ if self.cipd_input:
+ self.cipd_input._pre_put_hook()
+ if self.idempotent:
+ pinned = lambda p: cipd.is_pinned_version(p.version)
+ assert self.cipd_input.packages # checked by cipd_input._pre_put_hook
+ if any(not pinned(p) for p in self.cipd_input.packages):
+ raise datastore_errors.BadValueError(
+ 'an idempotent task cannot have unpinned packages; '
+ 'use tags or instance IDs as package versions')
class TaskRequest(ndb.Model):
"""Contains a user request.
« no previous file with comments | « appengine/swarming/server/config_test.py ('k') | appengine/swarming/server/task_request_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698