Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: migrate schedules_processor to use python-gitlab #706

Merged
merged 19 commits into from Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions gitlabform/gitlab/__init__.py
Expand Up @@ -22,7 +22,6 @@
from gitlabform.gitlab.variables import GitLabVariables
from gitlabform.gitlab.repositories import GitLabRepositories
from gitlabform.gitlab.resource_groups import GitLabResourceGroups
from gitlabform.gitlab.schedules import GitLabPipelineSchedules
from gitlabform.gitlab.integrations import GitLabIntegrations
from gitlabform.gitlab.users import GitLabUsers

Expand Down Expand Up @@ -65,7 +64,6 @@ class GitLab(
GitLabPipelines,
GitLabMembers,
GitLabUsers,
GitLabPipelineSchedules,
GitLabProjectBadges,
GitLabProjectDeployKeys,
GitLabProjectProtectedEnvironments,
Expand Down
122 changes: 0 additions & 122 deletions gitlabform/gitlab/schedules.py

This file was deleted.

175 changes: 101 additions & 74 deletions gitlabform/processors/project/schedules_processor.py
@@ -1,6 +1,9 @@
from logging import debug
from typing import Dict, List

from gitlab.base import RESTObjectList, RESTObject
from gitlab.v4.objects import Project, ProjectPipelineSchedule

from gitlabform.gitlab import GitLab
from gitlabform.processors.abstract_processor import AbstractProcessor

Expand All @@ -9,16 +12,21 @@
def __init__(self, gitlab: GitLab):
super().__init__("schedules", gitlab)

def _process_configuration(self, project_and_group: str, configuration: dict):
def _process_configuration(self, project_and_group: str, configuration: Dict):
configured_schedules = configuration.get("schedules", {})

enforce_schedules = configuration.get("schedules|enforce", False)

# Remove 'enforce' key from the config so that it's not treated as a "schedule"
if enforce_schedules:
configured_schedules.pop("enforce")

existing_schedules = self.gitlab.get_all_pipeline_schedules(project_and_group)
schedule_ids_by_description = self.__group_schedule_ids_by_description(
project: Project = self.gl.projects.get(project_and_group)
existing_schedules: List[RESTObject] | RESTObjectList = (

Check warning on line 25 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L24-L25

Added lines #L24 - L25 were not covered by tests
project.pipelineschedules.list()
)

schedule_ids_by_description: Dict = self._group_schedule_ids_by_description(

Check warning on line 29 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L29

Added line #L29 was not covered by tests
existing_schedules
)

Expand All @@ -29,115 +37,134 @@
if schedule_ids:
debug("Deleting pipeline schedules '%s'", schedule_description)
for schedule_id in schedule_ids:
self.gitlab.delete_pipeline_schedule(
project_and_group, schedule_id
)
project.pipelineschedules.get(schedule_id).delete()

Check warning on line 40 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L40

Added line #L40 was not covered by tests
else:
debug(
"Not deleting pipeline schedules '%s', because none exist",
schedule_description,
)
else:
entity_config = configured_schedules[schedule_description]

Check warning on line 47 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L47

Added line #L47 was not covered by tests

if schedule_ids and len(schedule_ids) == 1:
debug(
"Changing existing pipeline schedule '%s'", schedule_description
)
schedule_id = schedule_ids[0]
self.gitlab.take_ownership(project_and_group, schedule_id)
self.gitlab.update_pipeline_schedule(
project_and_group,
schedule_id,
configuration.get("schedules|" + schedule_description),
TimKnight-Opencast marked this conversation as resolved.
Show resolved Hide resolved
)
self.__set_schedule_variables(
project_and_group,
schedule_id,
configuration.get(
"schedules|" + schedule_description + "|variables"
),
schedule = project.pipelineschedules.get(schedule_ids[0])
self._update_existing_schedule(

Check warning on line 51 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L50-L51

Added lines #L50 - L51 were not covered by tests
entity_config, project, schedule, schedule_description
)
elif schedule_ids:
debug(
"Replacing existing pipeline schedules '%s'",
schedule_description,
)
for schedule_id in schedule_ids:
self.gitlab.delete_pipeline_schedule(
project_and_group, schedule_id
)
self.create_schedule_with_variables(
configuration, project_and_group, schedule_description
project.pipelineschedules.get(schedule_id).delete()

Check warning on line 60 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L60

Added line #L60 was not covered by tests

self._create_schedule_with_variables(

Check warning on line 62 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L62

Added line #L62 was not covered by tests
entity_config, project, schedule_description
)
else:
debug("Creating pipeline schedule '%s'", schedule_description)
self.create_schedule_with_variables(
configuration, project_and_group, schedule_description
self._create_schedule_with_variables(

Check warning on line 67 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L67

Added line #L67 was not covered by tests
entity_config, project, schedule_description
)

if enforce_schedules:
debug("Delete unconfigured schedules because enforce is enabled")

for schedule in existing_schedules:
schedule_description = schedule["description"]
schedule_id = schedule["id"]
self._delete_schedules_no_longer_in_config(

Check warning on line 74 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L74

Added line #L74 was not covered by tests
configured_schedules, existing_schedules, project
)

debug(f"processing {schedule_id}: {schedule_description}")
if schedule_description not in configured_schedules:
debug(
"Deleting pipeline schedule named '%s', because it is not in gitlabform configuration",
schedule_description,
)
self.gitlab.delete_pipeline_schedule(project_and_group, schedule_id)
def _update_existing_schedule(
self,
entity_config: Dict,
project: Project,
schedule_in_gitlab: ProjectPipelineSchedule,
schedule_description: str,
):

def create_schedule_with_variables(
self, configuration, project_and_group, schedule_description
if self._needs_update(schedule_in_gitlab.asdict(), entity_config):
debug("Changing existing pipeline schedule '%s'", schedule_description)

Check warning on line 87 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L86-L87

Added lines #L86 - L87 were not covered by tests
# In order to edit a Schedule created by someone else we need to take ownership:
# https://docs.gitlab.com/ee/ci/pipelines/schedules.html#take-ownership
shedule = project.pipelineschedules.get(schedule_in_gitlab.id)
shedule.take_ownership()
project.pipelineschedules.update(

Check warning on line 92 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L90-L92

Added lines #L90 - L92 were not covered by tests
schedule_in_gitlab.id,
{"description": schedule_description, **entity_config},
)
configured_variables = entity_config.get("variables")
if configured_variables is not None:
self._set_schedule_variables(

Check warning on line 98 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L96-L98

Added lines #L96 - L98 were not covered by tests
schedule_in_gitlab,
configured_variables,
)
else:
debug("No update required for pipeline schedule '%s'", schedule_description)

Check warning on line 103 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L103

Added line #L103 was not covered by tests

def _create_schedule_with_variables(
self,
entity_config: Dict,
project: Project,
schedule_description: str,
):
data = configuration.get("schedules|" + schedule_description)
created_schedule = self.gitlab.create_pipeline_schedule(
project_and_group,
schedule_description,
data.get("ref"),
data.get("cron"),
optional_data=data,
)
self.__set_schedule_variables(
project_and_group,
created_schedule.get("id"),
configuration.get("schedules|" + schedule_description + "|variables"),
)
schedule_data = {"description": schedule_description, **entity_config}
debug("Creating pipeline schedule using data: '%s'", schedule_data)

Check warning on line 112 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L111-L112

Added lines #L111 - L112 were not covered by tests

def __set_schedule_variables(self, project_and_group, schedule_id, variables):
schedule = self.gitlab.get_pipeline_schedule(project_and_group, schedule_id)
created_schedule_id = project.pipelineschedules.create(schedule_data).id
created_schedule = project.pipelineschedules.get(created_schedule_id)

Check warning on line 115 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L114-L115

Added lines #L114 - L115 were not covered by tests

existing_variables = schedule.get("variables")
if existing_variables:
debug(
"Deleting variables for pipeline schedule '%s'", schedule["description"]
configured_variables = entity_config.get("variables")
if configured_variables is not None:
self._set_schedule_variables(

Check warning on line 119 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L117-L119

Added lines #L117 - L119 were not covered by tests
created_schedule,
configured_variables,
)

created_schedule.save()

Check warning on line 124 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L124

Added line #L124 was not covered by tests

@staticmethod
def _set_schedule_variables(
schedule: ProjectPipelineSchedule, variables: Dict
) -> None:
attributes = schedule.attributes
existing_variables = attributes.get("variables")
if existing_variables:
debug("Deleting variables for pipeline schedule '%s'", schedule.description)

Check warning on line 133 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L130-L133

Added lines #L130 - L133 were not covered by tests

for variable in existing_variables:
self.gitlab.delete_pipeline_schedule_variable(
project_and_group, schedule_id, variable.get("key")
)
schedule.variables.delete(variable.get("key"))

Check warning on line 136 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L136

Added line #L136 was not covered by tests

if variables:
for variable_key, variable_data in variables.items():
self.gitlab.create_pipeline_schedule_variable(
project_and_group,
schedule_id,
variable_key,
variable_data.get("value"),
variable_data,
)
schedule.variables.create({"key": variable_key, **variable_data})

Check warning on line 140 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L140

Added line #L140 was not covered by tests

@staticmethod
def __group_schedule_ids_by_description(schedules) -> Dict[str, List[str]]:
def _group_schedule_ids_by_description(
schedules,
) -> Dict[str, List[str]]:
schedule_ids_by_description: Dict[str, List[str]] = {}

for schedule in schedules:
description = schedule["description"]
schedule_ids_by_description.setdefault(description, []).append(
schedule["id"]
schedule_ids_by_description.setdefault(schedule.description, []).append(

Check warning on line 149 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L149

Added line #L149 was not covered by tests
schedule.id
)

return schedule_ids_by_description

@staticmethod
def _delete_schedules_no_longer_in_config(
TimKnight-Opencast marked this conversation as resolved.
Show resolved Hide resolved
configured_schedules: Dict, existing_schedules, project: Project
) -> None:
schedule: ProjectPipelineSchedule
for schedule in existing_schedules:
schedule_description = schedule.description
schedule_id = schedule.id

Check warning on line 162 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L160-L162

Added lines #L160 - L162 were not covered by tests

debug(f"processing {schedule_id}: {schedule_description}")
if schedule_description not in configured_schedules:
debug(

Check warning on line 166 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L164-L166

Added lines #L164 - L166 were not covered by tests
"Deleting pipeline schedule named '%s', because it is not in gitlabform configuration",
schedule_description,
)
project.pipelineschedules.get(schedule_id).delete()

Check warning on line 170 in gitlabform/processors/project/schedules_processor.py

View check run for this annotation

Codecov / codecov/patch

gitlabform/processors/project/schedules_processor.py#L170

Added line #L170 was not covered by tests