moto/moto/codebuild/responses.py
2023-11-30 14:55:51 -01:00

189 lines
6.7 KiB
Python

import json
import re
from typing import Any, Dict, List
from moto.core.responses import BaseResponse
from .exceptions import (
InvalidInputException,
ResourceAlreadyExistsException,
ResourceNotFoundException,
)
from .models import CodeBuildBackend, codebuild_backends
def _validate_required_params_source(source: Dict[str, Any]) -> None:
if source["type"] not in [
"BITBUCKET",
"CODECOMMIT",
"CODEPIPELINE",
"GITHUB",
"GITHUB_ENTERPRISE",
"NO_SOURCE",
"S3",
]:
raise InvalidInputException("Invalid type provided: Project source type")
if "location" not in source:
raise InvalidInputException("Project source location is required")
if source["location"] == "":
raise InvalidInputException("Project source location is required")
def _validate_required_params_service_role(account_id: str, service_role: str) -> None:
if not service_role.startswith(f"arn:aws:iam::{account_id}:role/"):
raise InvalidInputException(
"Invalid service role: Service role account ID does not match caller's account"
)
def _validate_required_params_artifacts(artifacts: Dict[str, Any]) -> None:
if artifacts["type"] not in ["CODEPIPELINE", "S3", "NO_ARTIFACTS"]:
raise InvalidInputException("Invalid type provided: Artifact type")
if artifacts["type"] == "NO_ARTIFACTS":
if "location" in artifacts:
raise InvalidInputException(
"Invalid artifacts: artifact type NO_ARTIFACTS should have null location"
)
elif "location" not in artifacts or artifacts["location"] == "":
raise InvalidInputException("Project source location is required")
def _validate_required_params_environment(environment: Dict[str, Any]) -> None:
if environment["type"] not in [
"WINDOWS_CONTAINER",
"LINUX_CONTAINER",
"LINUX_GPU_CONTAINER",
"ARM_CONTAINER",
]:
raise InvalidInputException(f"Invalid type provided: {environment['type']}")
if environment["computeType"] not in [
"BUILD_GENERAL1_SMALL",
"BUILD_GENERAL1_MEDIUM",
"BUILD_GENERAL1_LARGE",
"BUILD_GENERAL1_2XLARGE",
]:
raise InvalidInputException(
f"Invalid compute type provided: {environment['computeType']}"
)
def _validate_required_params_project_name(name: str) -> None:
if len(name) >= 150:
raise InvalidInputException(
"Only alphanumeric characters, dash, and underscore are supported"
)
if not re.match(r"^[A-Za-z]{1}.*[^!£$%^&*()+=|?`¬{}@~#:;<>\\/\[\]]$", name):
raise InvalidInputException(
"Only alphanumeric characters, dash, and underscore are supported"
)
def _validate_required_params_id(build_id: str, build_ids: List[str]) -> None:
if ":" not in build_id:
raise InvalidInputException("Invalid build ID provided")
if build_id not in build_ids:
raise ResourceNotFoundException(f"Build {build_id} does not exist")
class CodeBuildResponse(BaseResponse):
@property
def codebuild_backend(self) -> CodeBuildBackend:
return codebuild_backends[self.current_account][self.region]
def list_builds_for_project(self) -> str:
_validate_required_params_project_name(self._get_param("projectName"))
if (
self._get_param("projectName")
not in self.codebuild_backend.codebuild_projects.keys()
):
name = self._get_param("projectName")
raise ResourceNotFoundException(
f"The provided project arn:aws:codebuild:{self.region}:{self.current_account}:project/{name} does not exist"
)
ids = self.codebuild_backend.list_builds_for_project(
self._get_param("projectName")
)
return json.dumps({"ids": ids})
def create_project(self) -> str:
_validate_required_params_source(self._get_param("source"))
service_role = self._get_param("serviceRole")
_validate_required_params_service_role(self.current_account, service_role)
_validate_required_params_artifacts(self._get_param("artifacts"))
_validate_required_params_environment(self._get_param("environment"))
_validate_required_params_project_name(self._get_param("name"))
if self._get_param("name") in self.codebuild_backend.codebuild_projects.keys():
name = self._get_param("name")
raise ResourceAlreadyExistsException(
f"Project already exists: arn:aws:codebuild:{self.region}:{self.current_account}:project/{name}"
)
project_metadata = self.codebuild_backend.create_project(
self._get_param("name"),
self._get_param("source"),
self._get_param("artifacts"),
self._get_param("environment"),
service_role=service_role,
)
return json.dumps({"project": project_metadata})
def list_projects(self) -> str:
project_metadata = self.codebuild_backend.list_projects()
return json.dumps({"projects": project_metadata})
def start_build(self) -> str:
_validate_required_params_project_name(self._get_param("projectName"))
if (
self._get_param("projectName")
not in self.codebuild_backend.codebuild_projects.keys()
):
name = self._get_param("projectName")
raise ResourceNotFoundException(
f"Project cannot be found: arn:aws:codebuild:{self.region}:{self.current_account}:project/{name}"
)
metadata = self.codebuild_backend.start_build(
self._get_param("projectName"),
self._get_param("sourceVersion"),
self._get_param("artifactsOverride"),
)
return json.dumps({"build": metadata})
def batch_get_builds(self) -> str:
for build_id in self._get_param("ids"):
if ":" not in build_id:
raise InvalidInputException("Invalid build ID provided")
metadata = self.codebuild_backend.batch_get_builds(self._get_param("ids"))
return json.dumps({"builds": metadata})
def list_builds(self) -> str:
ids = self.codebuild_backend.list_builds()
return json.dumps({"ids": ids})
def delete_project(self) -> str:
_validate_required_params_project_name(self._get_param("name"))
self.codebuild_backend.delete_project(self._get_param("name"))
return "{}"
def stop_build(self) -> str:
_validate_required_params_id(
self._get_param("id"), self.codebuild_backend.list_builds()
)
metadata = self.codebuild_backend.stop_build(self._get_param("id"))
return json.dumps({"build": metadata})