| OLD | NEW |
| 1 # Copyright 2013 The LUCI Authors. All rights reserved. | 1 # Copyright 2013 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed by the Apache v2.0 license that can be | 2 # Use of this source code is governed by the Apache v2.0 license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Instance specific settings.""" | 5 """Instance specific settings.""" |
| 6 | 6 |
| 7 import logging | 7 import logging |
| 8 import posixpath | 8 import posixpath |
| 9 import re |
| 9 | 10 |
| 10 from components import config | 11 from components import config |
| 11 from components import gitiles | 12 from components import gitiles |
| 12 from components import net | 13 from components import net |
| 13 from components import utils | 14 from components import utils |
| 14 from components.config import validation | 15 from components.config import validation |
| 15 | 16 |
| 16 from proto import config_pb2 | 17 from proto import config_pb2 |
| 17 from server import task_request | |
| 18 | 18 |
| 19 import cipd |
| 19 | 20 |
| 20 SETTINGS_CFG_FILENAME = 'settings.cfg' | 21 SETTINGS_CFG_FILENAME = 'settings.cfg' |
| 21 SECONDS_IN_YEAR = 60 * 60 * 24 * 365 | 22 SECONDS_IN_YEAR = 60 * 60 * 24 * 365 |
| 23 NAMESPACE_RE = re.compile(r'^[a-z0-9A-Z\-._]+$') |
| 22 | 24 |
| 23 | 25 |
| 24 ConfigApi = config.ConfigApi | 26 ConfigApi = config.ConfigApi |
| 25 | 27 |
| 26 | 28 |
| 29 def validate_url(value, ctx): |
| 30 if not value: |
| 31 ctx.error('is not set') |
| 32 elif not value.startswith(('https://', 'http://')): |
| 33 ctx.error('must start with "https://" or "http://"') |
| 34 |
| 35 |
| 27 def validate_isolate_settings(cfg, ctx): | 36 def validate_isolate_settings(cfg, ctx): |
| 28 if bool(cfg.default_server) != bool(cfg.default_namespace): | 37 if bool(cfg.default_server) != bool(cfg.default_namespace): |
| 29 ctx.error( | 38 ctx.error( |
| 30 'either specify both default_server and default_namespace or none') | 39 'either specify both default_server and default_namespace or none') |
| 31 elif cfg.default_server: | 40 elif cfg.default_server: |
| 32 if not cfg.default_server.startswith(('https://', 'http://')): | 41 with ctx.prefix('default_server '): |
| 33 ctx.error('default_server must start with "https://" or "http://"') | 42 validate_url(cfg.default_server, ctx) |
| 34 | 43 |
| 35 if not task_request.NAMESPACE_RE.match(cfg.default_namespace): | 44 if not NAMESPACE_RE.match(cfg.default_namespace): |
| 36 ctx.error('invalid namespace "%s"', cfg.default_namespace) | 45 ctx.error('invalid namespace "%s"', cfg.default_namespace) |
| 37 | 46 |
| 38 | 47 |
| 48 def validate_cipd_package(cfg, ctx): |
| 49 if not cipd.is_valid_package_name_template(cfg.package_name): |
| 50 ctx.error('invalid package_name "%s"', cfg.package_name) |
| 51 if not cipd.is_valid_version(cfg.version): |
| 52 ctx.error('invalid version "%s"', cfg.version) |
| 53 |
| 54 |
| 55 def validate_cipd_settings(cfg, ctx=None): |
| 56 """Validates CipdSettings message stored in settings.cfg.""" |
| 57 ctx = ctx or validation.Context.raise_on_error() |
| 58 with ctx.prefix('default_server '): |
| 59 validate_url(cfg.default_server, ctx) |
| 60 |
| 61 with ctx.prefix('default_client_package: '): |
| 62 validate_cipd_package(cfg.default_client_package, ctx) |
| 63 |
| 64 |
| 39 @validation.self_rule(SETTINGS_CFG_FILENAME, config_pb2.SettingsCfg) | 65 @validation.self_rule(SETTINGS_CFG_FILENAME, config_pb2.SettingsCfg) |
| 40 def validate_settings(cfg, ctx): | 66 def validate_settings(cfg, ctx): |
| 41 """Validates settings.cfg file against proto message schema.""" | 67 """Validates settings.cfg file against proto message schema.""" |
| 42 def within_year(value): | 68 def within_year(value): |
| 43 if value < 0: | 69 if value < 0: |
| 44 ctx.error('cannot be negative') | 70 ctx.error('cannot be negative') |
| 45 elif value > SECONDS_IN_YEAR: | 71 elif value > SECONDS_IN_YEAR: |
| 46 ctx.error('cannot be more than a year') | 72 ctx.error('cannot be more than a year') |
| 47 | 73 |
| 48 with ctx.prefix('bot_death_timeout_secs '): | 74 with ctx.prefix('bot_death_timeout_secs '): |
| 49 within_year(cfg.bot_death_timeout_secs) | 75 within_year(cfg.bot_death_timeout_secs) |
| 50 with ctx.prefix('reusable_task_age_secs '): | 76 with ctx.prefix('reusable_task_age_secs '): |
| 51 within_year(cfg.reusable_task_age_secs) | 77 within_year(cfg.reusable_task_age_secs) |
| 52 | 78 |
| 53 if cfg.HasField('isolate'): | 79 if cfg.HasField('isolate'): |
| 54 with ctx.prefix('isolate: '): | 80 with ctx.prefix('isolate: '): |
| 55 validate_isolate_settings(cfg.isolate, ctx) | 81 validate_isolate_settings(cfg.isolate, ctx) |
| 56 | 82 |
| 83 if cfg.HasField('cipd'): |
| 84 with ctx.prefix('cipd: '): |
| 85 validate_cipd_settings(cfg.cipd, ctx) |
| 86 |
| 57 | 87 |
| 58 @utils.memcache('config:get_configs_url', time=60) | 88 @utils.memcache('config:get_configs_url', time=60) |
| 59 def _get_configs_url(): | 89 def _get_configs_url(): |
| 60 """Returns URL where luci-config fetches configs from.""" | 90 """Returns URL where luci-config fetches configs from.""" |
| 61 url = None | 91 url = None |
| 62 try: | 92 try: |
| 63 url = config.get_config_set_location(config.self_config_set()) | 93 url = config.get_config_set_location(config.self_config_set()) |
| 64 except net.Error: | 94 except net.Error: |
| 65 logging.info( | 95 logging.info( |
| 66 'Could not get configs URL. Possibly config directory for this ' | 96 'Could not get configs URL. Possibly config directory for this ' |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 'config_service_url': ( | 151 'config_service_url': ( |
| 122 'https://%s' % cfg_service_hostname if cfg_service_hostname else '' | 152 'https://%s' % cfg_service_hostname if cfg_service_hostname else '' |
| 123 ), | 153 ), |
| 124 } | 154 } |
| 125 | 155 |
| 126 | 156 |
| 127 @utils.cache_with_expiration(60) | 157 @utils.cache_with_expiration(60) |
| 128 def settings(): | 158 def settings(): |
| 129 """Loads settings from an NDB-based cache or a default one if not present.""" | 159 """Loads settings from an NDB-based cache or a default one if not present.""" |
| 130 return _get_settings()[1] | 160 return _get_settings()[1] |
| OLD | NEW |