def build_generic(self, tmp_vars, fields, camel_case=True, debug=False): if debug: print('build_generic(): tmp_vars=%s, fields=%s' % (tmp_vars, fields)) ret = dict() for field in fields: field_value = tmp_vars.get(field, None) value_type = None if isinstance(field_value, list): value_type = 'list' elif isinstance(field_value, dict): value_type = 'dict' if value_type == 'list': if fields[field].get( 'subtype', None) == 'dict' and 'fields' in fields[field]: ret2 = [] for entry in field_value: ret3 = self.build_generic(entry, fields[field]['fields'], camel_case=camel_case, debug=debug) if ret3: ret2.append(ret3) if ret2: ret[(underscore_to_camelcase(field) if camel_case else field)] = ret2 else: if field_value: ret[(underscore_to_camelcase(field) if camel_case else field)] = field_value elif value_type == 'dict': if fields[field].get('fields', None) and field_value: ret2 = self.build_generic(field_value, fields[field]['fields'], camel_case=camel_case, debug=debug) if ret2: ret[(underscore_to_camelcase(field) if camel_case else field)] = ret2 else: if field_value: ret[(underscore_to_camelcase(field) if camel_case else field)] = field_value else: if field_value is not None: ret[(underscore_to_camelcase(field) if camel_case else field)] = field_value return ret
def generate_output(self, app_vars): # Basic structure data = { 'apiVersion': 'v1', 'kind': 'Secret', } data['metadata'] = self.build_metadata(app_vars['APP']['metadata']) for field in ('type', ): data[underscore_to_camelcase(field)] = app_vars['APP'][field] if app_vars['APP']['string_data']: data['stringData'] = app_vars['APP']['string_data'] if app_vars['APP']['data']: tmp_data = dict() for key in app_vars['APP']['data']: # Values under 'data' should be base64-encoded # We have to jump through the hoops of encoding/decoding it because the # py3 b64encode() function expects a bytestring, and then the YAML encoder # tries to double-encode the resulting bytestring, so we convert it back # to a string tmp_value = app_vars['APP']['data'][key].encode("utf-8") tmp_data[key] = base64.b64encode(tmp_value).decode('utf-8') data['data'] = tmp_data data = self._template.render_template(data, app_vars) output = yaml_dump(data) return (output, self.get_output_filename_suffix(data))
def build_port_definitions(self, app_vars, data): port_definitions = [] tmp_vars = app_vars.copy() for port_index, port in enumerate(app_vars['APP']['port_definitions']): tmp_vars.update(dict(port=port, port_index=port_index)) tmp_port = { "port": int(port['port']), } for field in ('name', 'protocol'): if port[field] is not None: tmp_port[underscore_to_camelcase(field)] = port[field] # Port labels port_labels = {} for label_index, label in enumerate(port['labels']): tmp_vars.update(dict(label=label, label_index=label_index)) if label[ 'condition'] is None or self._template.evaluate_condition( label['condition'], tmp_vars): port_labels[self._template.render_template( label['name'], tmp_vars)] = self._template.render_template( label['value'], tmp_vars) if port_labels: tmp_port['labels'] = port_labels # Render templates now so that loop vars can be used tmp_port = self._template.render_template(tmp_port, tmp_vars) port_definitions.append(tmp_port) if port_definitions: data['portDefinitions'] = port_definitions if app_vars['APP']['require_ports'] is not None: data['requirePorts'] = app_vars['APP']['require_ports']
def build_port_mappings(self, app_vars, data): port_mappings = [] tmp_vars = app_vars.copy() for port_index, port in enumerate(app_vars['APP']['ports']): tmp_vars.update(dict(port=port, port_index=port_index)) tmp_port = { "protocol": port['protocol'], } for field in ('container_port', 'host_port', 'service_port'): if port[field] is not None: tmp_port[underscore_to_camelcase(field)] = int(port[field]) # Port labels port_labels = {} for label_index, label in enumerate(port['labels']): tmp_vars.update(dict(label=label, label_index=label_index)) if label[ 'condition'] is None or self._template.evaluate_condition( label['condition'], tmp_vars): port_labels[self._template.render_template( label['name'], tmp_vars)] = self._template.render_template( label['value'], tmp_vars) if port_labels: tmp_port['labels'] = port_labels # Render templates now so that loop vars can be used tmp_port = self._template.render_template(tmp_port, tmp_vars) port_mappings.append(tmp_port) if port_mappings: data['container']['docker']['portMappings'] = port_mappings
def build_spec_selector(self, app_vars, data): tmp_selector = dict() for field in ('match_expressions', 'match_labels'): if app_vars['APP']['spec']['selector'][field]: tmp_selector[underscore_to_camelcase( field)] = app_vars['APP']['spec']['selector'][field] if tmp_selector: data['spec']['selector'] = tmp_selector
def build_unreachable_strategy(self, app_vars, data): strategy = {} app_vars_section = app_vars['APP']['unreachable_strategy'] for field in ('inactive_after_seconds', 'expunge_after_seconds'): if app_vars_section[field] is not None: strategy[underscore_to_camelcase(field)] = int( app_vars_section[field]) if strategy: data['unreachableStrategy'] = strategy
def build_upgrade_strategy(self, app_vars, data): strategy = {} app_vars_section = app_vars['APP']['upgrade_strategy'] for field in ('minimum_health_capacity', 'maximum_over_capacity'): if app_vars_section[field] is not None: strategy[underscore_to_camelcase(field)] = float( app_vars_section[field]) if strategy: data['upgradeStrategy'] = strategy
def build_spec(self, app_vars, data): for field in ('pod_management_policy', 'replicas', 'revision_history_limit', 'service_name'): if app_vars['APP']['spec'][field] is not None: data['spec'][underscore_to_camelcase( field)] = app_vars['APP']['spec'][field] self.build_spec_selector(app_vars, data) self.build_spec_update_strategy(app_vars, data) self.build_spec_template(app_vars, data) self.build_spec_volume_claim(app_vars, data)
def build_spec(self, app_vars, data): for field in ('min_ready_seconds', 'paused', 'progress_deadline_seconds', 'replicas', 'revision_history_limit'): if app_vars['APP']['spec'][field] is not None: data['spec'][underscore_to_camelcase( field)] = app_vars['APP']['spec'][field] self.build_spec_selector(app_vars, data) self.build_spec_strategy(app_vars, data) self.build_spec_template(app_vars, data)
def generate_output(self, app_vars): # Basic structure data = { "id": app_vars['APP']['id'], "cpus": app_vars['APP']['cpus'], "mem": app_vars['APP']['mem'], "disk": app_vars['APP']['disk'], "instances": app_vars['APP']['instances'], # TODO: add support for container types other than 'DOCKER' "container": { "type": "DOCKER", "volumes": [], # TODO: make various attributes configurable "docker": { "image": app_vars['APP']['image'], "privileged": app_vars['APP']['docker_privileged'], "parameters": app_vars['APP']['docker_parameters'], "forcePullImage": True } }, } # Constraints if app_vars['APP']['constraints']: data['constraints'] = app_vars['APP']['constraints'] # Ports self.build_port_mappings(app_vars, data) self.build_port_definitions(app_vars, data) # Container labels self.build_container_labels(app_vars, data) # Networks self.build_networks(app_vars, data) # Volumes self.build_volumes(app_vars, data) # Environment if app_vars['APP']['env'] is not None: data['env'] = app_vars['APP']['env'] # Secrets self.build_secrets(app_vars, data) # Fetch config self.build_fetch_config(app_vars, data) # Health checks self.build_health_checks(app_vars, data) # Upgrade/unreachable strategies self.build_upgrade_strategy(app_vars, data) self.build_unreachable_strategy(app_vars, data) # Misc attributes for field in ('labels', 'args', 'cmd', 'accepted_resource_roles'): if app_vars['APP'][field]: data[underscore_to_camelcase(field)] = app_vars['APP'][field] output = json_dump(self._template.render_template(data, app_vars)) return output
def build_volumes(self, app_vars, data): if app_vars['APP']['volumes']: volumes = [] for volume_index, volume in enumerate(app_vars['APP']['volumes']): tmp_volume = {} for field in ('container_path', 'host_path', 'mode'): if volume[field] is not None: tmp_volume[underscore_to_camelcase( field)] = volume[field] if volume['persistent']: tmp_persistent = {} for field in ('type', 'size', 'profile_name', 'max_size'): if volume['persistent'][field] is not None: tmp_persistent[underscore_to_camelcase( field)] = volume['persistent'][field] if volume['persistent']['constraints']: tmp_persistent['constraints'] = volume['persistent'][ 'constraints'] if tmp_persistent: tmp_volume['persistent'] = tmp_persistent volumes.append(tmp_volume) data['container']['volumes'] = volumes
def build_spec_strategy(self, app_vars, data): tmp_strategy = dict() if app_vars['APP']['spec']['strategy']['type'] is not None: tmp_strategy['type'] = app_vars['APP']['spec']['strategy']['type'] if app_vars['APP']['spec']['strategy']['rolling_update']: tmp_rolling_update = dict() for field in ('max_surge', 'max_unavailable'): if app_vars['APP']['spec']['strategy']['rolling_update'].get( field, None) is not None: tmp_rolling_update[underscore_to_camelcase( field)] = app_vars['APP']['spec']['strategy'][ 'rolling_update'][field] if tmp_rolling_update: tmp_strategy['rollingUpdate'] = tmp_rolling_update if tmp_strategy: data['spec']['strategy'] = tmp_strategy
def build_health_checks(self, app_vars, data): health_checks = [] tmp_vars = app_vars.copy() for check_index, check in enumerate(app_vars['APP']['health_checks']): tmp_vars.update(dict(check=check, check_index=check_index)) tmp_check = {} for field in ('grace_period_seconds', 'interval_seconds', 'timeout_seconds', 'delay_seconds', 'max_consecutive_failures', 'path', 'port_index', 'port', 'protocol'): if check[field] is not None: tmp_check[underscore_to_camelcase(field)] = check[field] if check['command'] is not None: tmp_check.update( dict(protocol='COMMAND', command=dict(value=check['command']))) # Render templates now so that loop vars can be used tmp_check = self._template.render_template(tmp_check, tmp_vars) health_checks.append(tmp_check) if health_checks: data['healthChecks'] = health_checks
def build_metadata(self, tmp_vars): tmp_metadata = {} for field in ('annotations', 'labels', 'name', 'namespace'): if tmp_vars[field] is not None: tmp_metadata[underscore_to_camelcase(field)] = tmp_vars[field] return tmp_metadata