class Profile(AttrsClass): """ firstname, lastname, ssn are generic data type field. """ firstname = AttrsClass.ib_str() lastname = AttrsClass.ib_str() ssn = AttrsClass.ib_str()
class RepoConfig(AttrsClass): repo_name = AttrsClass.ib_str() registry = AttrsClass.ib_str() docker_hub_username = AttrsClass.ib_str(default=None) aws_ecr_life_cycle_expire_days = AttrsClass.ib_int(default=365) class RegistryOptions: docker_hub = "docker_hub" aws_ecr = "aws_ecr" _valid_registry_options = [ RegistryOptions.docker_hub, RegistryOptions.aws_ecr, ] @registry.validator def check_registry(self, attr, value): if value not in self._valid_registry_options: raise ValueError( f"'{value}' is a invalid registry! Has to be one of {self._valid_registry_options}" ) @property def aws_ecr_life_cycle_policy(self): return { "rules": [{ "rulePriority": 1, "description": "Expire images older than {} days".format( self.aws_ecr_life_cycle_expire_days), "selection": { "tagStatus": "untagged", "countType": "sinceImagePushed", "countUnit": "days", "countNumber": self.aws_ecr_life_cycle_expire_days }, "action": { "type": "expire" } }] } def __attrs_post_init__(self): if self.registry == self.RegistryOptions.docker_hub: if not isinstance(self.docker_hub_username, str): raise ValueError("docker_hub_username config is invalid!") @classmethod def from_json(cls, path): """ :rtype: RepoConfig """ if not Path(path).exists(): raise EnvironmentError(f"{path} doesn't exists!") return cls(**json_load(path))
class People(AttrsClass): """ - ``profile`` is nested field. - ``degrees`` is collection type field. """ id = AttrsClass.ib_int() profile = Profile.ib_nested() degrees = Degree.ib_list_of_nested()
class Application(AttrsClass): git_dir = AttrsClass.ib_str() repos_dir = AttrsClass.ib_str() config = AppConfig.ib_nested(default=None) def plan(self): for repo_dir in Path(self.repos_dir).select_dir(recursive=False): try: repo = Repo(path=repo_dir.abspath) print(repo) for tag_dir in Path(repo.path).select_dir(recursive=False): try: tag = Tag(path=tag_dir.abspath, repo=repo) print(tag) except NotValidTagDirError: pass except NotValidRepoDirError: pass
class AppConfig(AttrsClass): path = AttrsClass.ib_str() project_name = AttrsClass.ib_str() aws_profile = AttrsClass.ib_str() dynamodb_table_name = AttrsClass.ib_str(default="rabbit-docker-cicd-pipeline-state") repo_config_file = AttrsClass.ib_str(default="repo-config.json") tag_config_file = AttrsClass.ib_str(default="tag-config.json") docker_file = AttrsClass.ib_str(default="Dockerfile")
class TagConfig(AttrsClass): tag_name = AttrsClass.ib_str() @classmethod def from_json(cls, path): """ :rtype: TagConfig """ if not Path(path).exists(): raise EnvironmentError(f"{path} doesn't exists!") return cls(**json_load(path))
class Repo(AttrsClass): path = AttrsClass.ib_str() config = attr.ib(default=None) def __attrs_post_init__(self): try: self.config = RepoConfig.from_json( Path(self.path, app_config.repo_config_file).abspath) except Exception as e: raise NotValidRepoDirError( NotValidRepoDirError.tpl_config_error.format( self.path, app_config.repo_config_file, str(e), ))
class Tag(AttrsClass): path = AttrsClass.ib_str() repo = Repo.ib_nested() config = attr.ib(default=None) def __attrs_post_init__(self): try: self.config = TagConfig.from_json( Path(self.path, app_config.tag_config_file)) except Exception as e: raise NotValidTagDirError( NotValidTagDirError.tpl_config_error.format( self.path, app_config.tag_config_file, str(e), )) if not Path(self.path, app_config.docker_file).exists(): raise NotValidTagDirError("{} not found in {}".format( app_config.docker_file, self.path, ))
class Degree(AttrsClass): name = AttrsClass.ib_str() year = AttrsClass.ib_int()