blob: 760217cc282e9a9123c28b715c0e8c237b1fee2a [file] [log] [blame]
Torsten Rasmussen8408af62021-11-22 10:29:56 +01001# Copyright (c) 2022 Nordic Semiconductor ASA
2#
3# SPDX-License-Identifier: Apache-2.0
4
5'''Domain handling for west extension commands.
6
7This provides parsing of domains yaml file and creation of objects of the
8Domain class.
9'''
10
Grzegorz Swiderski9bbf7e52023-09-28 09:36:36 +020011from dataclasses import dataclass
12
Torsten Rasmussen8408af62021-11-22 10:29:56 +010013import yaml
14import pykwalify.core
Daniel DeGrassec303c6f2022-11-01 12:16:39 -050015import logging
Torsten Rasmussen8408af62021-11-22 10:29:56 +010016
17DOMAINS_SCHEMA = '''
18## A pykwalify schema for basic validation of the structure of a
19## domains YAML file.
20##
21# The domains.yaml file is a simple list of domains from a multi image build
22# along with the default domain to use.
23type: map
24mapping:
25 default:
26 required: true
27 type: str
28 build_dir:
29 required: true
30 type: str
31 domains:
Grzegorz Swiderskif82e2ef2023-09-28 09:36:01 +020032 required: true
Torsten Rasmussen8408af62021-11-22 10:29:56 +010033 type: seq
34 sequence:
35 - type: map
36 mapping:
37 name:
38 required: true
39 type: str
40 build_dir:
41 required: true
42 type: str
Grzegorz Swiderski05d77692023-09-25 12:45:10 +020043 flash_order:
44 required: false
45 type: seq
46 sequence:
47 - type: str
Torsten Rasmussen8408af62021-11-22 10:29:56 +010048'''
49
50schema = yaml.safe_load(DOMAINS_SCHEMA)
Daniel DeGrassec303c6f2022-11-01 12:16:39 -050051logger = logging.getLogger('build_helpers')
52# Configure simple logging backend.
53formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
54handler = logging.StreamHandler()
55handler.setFormatter(formatter)
56logger.addHandler(handler)
Torsten Rasmussen8408af62021-11-22 10:29:56 +010057
58
59class Domains:
60
Grzegorz Swiderski652b0a82023-09-28 09:36:18 +020061 def __init__(self, domains_yaml):
62 try:
63 data = yaml.safe_load(domains_yaml)
64 pykwalify.core.Core(source_data=data,
65 schema_data=schema).validate()
66 except (yaml.YAMLError, pykwalify.errors.SchemaError):
67 logger.critical(f'malformed domains.yaml')
68 exit(1)
69
Grzegorz Swiderskif82e2ef2023-09-28 09:36:01 +020070 self._build_dir = data['build_dir']
Grzegorz Swiderski05d77692023-09-25 12:45:10 +020071 self._domains = {
72 d['name']: Domain(d['name'], d['build_dir'])
Grzegorz Swiderskif82e2ef2023-09-28 09:36:01 +020073 for d in data['domains']
Grzegorz Swiderski05d77692023-09-25 12:45:10 +020074 }
Grzegorz Swiderski05d77692023-09-25 12:45:10 +020075
Grzegorz Swiderskif82e2ef2023-09-28 09:36:01 +020076 # In the YAML data, the values for "default" and "flash_order"
77 # must not name any domains that aren't listed under "domains".
78 # Now that self._domains has been initialized, we can leverage
79 # the common checks in self.get_domain to verify this.
80 self._default_domain = self.get_domain(data['default'])
Lukasz Mrugala2fcf4e32023-10-05 13:41:15 +020081 self._flash_order = self.get_domains(data.get('flash_order', []))
Torsten Rasmussen8408af62021-11-22 10:29:56 +010082
83 @staticmethod
84 def from_file(domains_file):
Grzegorz Swiderski652b0a82023-09-28 09:36:18 +020085 '''Load domains from a domains.yaml file.
Torsten Rasmussen8408af62021-11-22 10:29:56 +010086 '''
87 try:
88 with open(domains_file, 'r') as f:
Grzegorz Swiderski652b0a82023-09-28 09:36:18 +020089 domains_yaml = f.read()
Torsten Rasmussen8408af62021-11-22 10:29:56 +010090 except FileNotFoundError:
Daniel DeGrassec303c6f2022-11-01 12:16:39 -050091 logger.critical(f'domains.yaml file not found: {domains_file}')
92 exit(1)
Torsten Rasmussen8408af62021-11-22 10:29:56 +010093
Grzegorz Swiderski652b0a82023-09-28 09:36:18 +020094 return Domains(domains_yaml)
Torsten Rasmussen8408af62021-11-22 10:29:56 +010095
96 @staticmethod
Grzegorz Swiderski652b0a82023-09-28 09:36:18 +020097 def from_yaml(domains_yaml):
98 '''Load domains from a string with YAML contents.
Torsten Rasmussen8408af62021-11-22 10:29:56 +010099 '''
Grzegorz Swiderski652b0a82023-09-28 09:36:18 +0200100 return Domains(domains_yaml)
Torsten Rasmussen8408af62021-11-22 10:29:56 +0100101
Grzegorz Swiderski05d77692023-09-25 12:45:10 +0200102 def get_domains(self, names=None, default_flash_order=False):
Grzegorz Swiderskif82e2ef2023-09-28 09:36:01 +0200103 if names is None:
Grzegorz Swiderski05d77692023-09-25 12:45:10 +0200104 if default_flash_order:
105 return self._flash_order
106 return list(self._domains.values())
Grzegorz Swiderskif82e2ef2023-09-28 09:36:01 +0200107 return list(map(self.get_domain, names))
Torsten Rasmussen8408af62021-11-22 10:29:56 +0100108
Grzegorz Swiderskif82e2ef2023-09-28 09:36:01 +0200109 def get_domain(self, name):
110 found = self._domains.get(name)
111 if not found:
112 logger.critical(f'domain "{name}" not found, '
113 f'valid domains are: {", ".join(self._domains)}')
114 exit(1)
115 return found
Torsten Rasmussen8408af62021-11-22 10:29:56 +0100116
117 def get_default_domain(self):
118 return self._default_domain
119
120 def get_top_build_dir(self):
121 return self._build_dir
122
123
Grzegorz Swiderski9bbf7e52023-09-28 09:36:36 +0200124@dataclass
Torsten Rasmussen8408af62021-11-22 10:29:56 +0100125class Domain:
126
Grzegorz Swiderski9bbf7e52023-09-28 09:36:36 +0200127 name: str
128 build_dir: str