Skip to content

Commit

Permalink
Merge branch 'main' into repo-file-yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
jajreidy authored Nov 20, 2024
2 parents 87ae76c + e4cfe3f commit a7f1a9a
Show file tree
Hide file tree
Showing 18 changed files with 279 additions and 56 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cloudimg>=1.15.0
pubtools>=1.3.0
more_executors>=2.11.4
pushcollector>=1.3.0
pushsource>=2.48.1
pushsource>=2.50.0
strenum>=0.4.15
starmap-client>=2.1.1
cloudpub>=1.2.1
7 changes: 4 additions & 3 deletions src/pubtools/_marketplacesvm/cloud_providers/ms_azure.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,10 @@ def _delete_push_images(self, push_item, **kwargs) -> Tuple[VHDPushItem, Any]:
Returns:
A tuple of VHDPushItem and None at the moment.
"""
# TODO: Add delete functionality to Azure
LOG.info("Deleting of Azure images from a push is not implemented yet")
return push_item, None
name = self._name_from_push_item(push_item)
delete_meta_kwargs = {"image_name": name, "container": UPLOAD_CONTAINER_NAME}
self.upload_svc.delete(**delete_meta_kwargs)
return push_item

def ensure_offer_is_writable(self, destination: str, nochannel: bool) -> None:
"""
Expand Down
50 changes: 35 additions & 15 deletions src/pubtools/_marketplacesvm/tasks/delete/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import json
import logging
import os
from typing import Any, Dict, Iterator, List, Tuple
from typing import Any, Dict, Iterator, List, Optional, Tuple

from attrs import asdict, evolve
from pushsource import AmiPushItem, Source, VMIPushItem
from pushsource import AmiPushItem, Source, VHDPushItem, VMIPushItem

from ...arguments import SplitAndExtend
from ...services import CloudService, CollectorService
Expand All @@ -28,20 +28,20 @@ def __init__(self, *args, **kwargs):
super(VMDelete, self).__init__(*args, **kwargs)

@property
def raw_items(self) -> Iterator[AmiPushItem]:
def raw_items(self) -> Iterator[VMIPushItem]:
"""
Load all push items from the given source(s) and yield them.
Yields:
The AmiPushItems from the given sources.
The VMIPushItems from the given sources.
"""
for source_url in self.args.source:
with Source.get(source_url) as source:
log.info("Loading items from %s", source_url)
for item in source:
if not isinstance(item, AmiPushItem):
if not isinstance(item, VMIPushItem):
log.warning(
"Push Item %s at %s is not an AmiPushItem, dropping it from the queue.",
"Push Item %s at %s is not a VMIPushItem, dropping it from the queue.",
item.name,
item.src,
)
Expand Down Expand Up @@ -142,7 +142,9 @@ def _get_provider_details(self, push_item: VMIPushItem) -> Tuple[str, List[str]]
account = self._convert_provider_name(provider)
return provider, account

def _set_ami_invisible(self, push_item: AmiPushItem, provider: str) -> None:
def _set_ami_invisible(self, push_item: AmiPushItem, provider: Optional[str] = None) -> None:
if not provider:
return
img_id = push_item.image_id
log.debug("Marking AMI %s as invisible on RHSM for the provider %s.", img_id, provider)
try:
Expand All @@ -156,43 +158,61 @@ def _set_ami_invisible(self, push_item: AmiPushItem, provider: str) -> None:
exc_info=True,
)

def _delete(
def _delete_vmi(
self,
push_item: VMIPushItem,
marketplaces: List[str],
image_reference: str,
provider: Optional[str] = None,
**kwargs,
) -> VMIPushItem:
provider, marketplaces = self._get_provider_details(push_item)
if push_item.build in self.args.builds:
if self.args.dry_run:
self._set_ami_invisible(push_item, provider)
log.info("Would have deleted: %s in build %s", push_item.image_id, push_item.build)
log.info("Would have deleted: %s in build %s", image_reference, push_item.build)
self._SKIPPED = True
pi = evolve(push_item, state=State.SKIPPED)
return pi
# Cycle through potential marketplaces, this only matters in AmiProducts
# as the build could exist in either aws-na or aws-emea.
for marketplace in marketplaces:
self._set_ami_invisible(push_item, provider)
log.info(
"Deleting %s in account %s",
push_item.image_id,
image_reference,
marketplace,
)
pi, _ = self.cloud_instance(marketplace).delete_push_images(
push_item, keep_snapshot=self.args.keep_snapshot, **kwargs
)
log.info(
"Delete finished for %s in account %s",
push_item.image_id,
image_reference,
marketplace,
)
pi = evolve(pi, state=State.DELETED)
return pi
log.info("Skipped: %s in build %s", push_item.image_id, push_item.build)
log.info("Skipped: %s in build %s", image_reference, push_item.build)
self._SKIPPED = True
pi = evolve(push_item, state=State.SKIPPED)
return pi

def _delete(
self,
push_item: VMIPushItem,
**kwargs,
) -> VMIPushItem:
if isinstance(push_item, AmiPushItem):
image_ref = push_item.image_id
provider, marketplaces = self._get_provider_details(push_item)
elif isinstance(push_item, VHDPushItem):
image_ref = push_item.name
provider = None
if push_item.cloud_info:
marketplaces = [push_item.cloud_info.account]
else:
# If we don't have cloud info we will need to try either
marketplaces = ["azure-na", "azure-emea"]
return self._delete_vmi(push_item, marketplaces, image_ref, provider, **kwargs)

def add_args(self):
"""Include the required CLI arguments for VMDelete."""
super(VMDelete, self).add_args()
Expand Down
66 changes: 61 additions & 5 deletions tests/delete/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from typing import List
from datetime import datetime
from typing import Any, Dict, List

import pytest
from pushsource import (
Expand All @@ -9,6 +10,7 @@
AmiSecurityGroup,
KojiBuildInfo,
VHDPushItem,
VMIRelease,
)

from pubtools._marketplacesvm.tasks.delete.command import VMDelete
Expand Down Expand Up @@ -44,6 +46,26 @@ def ami_release() -> AmiRelease:
return AmiRelease(**params)


@pytest.fixture
def release_params() -> Dict[str, Any]:
return {
"product": "sample-product",
"version": "7.0",
"arch": "x86_64",
"respin": 1,
"date": datetime.now(),
}


@pytest.fixture
def push_item_params() -> Dict[str, str]:
return {
"name": "name",
"description": "",
"build_info": KojiBuildInfo(name="test-build", version="7.0", release="20230101"),
}


@pytest.fixture
def security_group() -> AmiSecurityGroup:
params = {
Expand Down Expand Up @@ -149,22 +171,56 @@ def aws_rhcos_push_item(ami_release: AmiRelease, security_group: AmiSecurityGrou


@pytest.fixture
def pub_response(aws_rhcos_push_item: AmiPushItem, aws_push_item: AmiPushItem) -> List[AmiPushItem]:
def vhd_push_item(release_params: Dict[str, Any], push_item_params: Dict[str, Any]) -> VHDPushItem:
"""Return a minimal VHDPushItem."""
release = VMIRelease(**release_params)
push_item_params.update(
{
"name": "azure-testing.vhd.xz",
"release": release,
"src": "mnt/azure/azure-testing.vhd.xz",
"dest": ["azure-testing"],
"build": "azure-testing",
}
)
return VHDPushItem(**push_item_params)


@pytest.fixture
def pub_response_ami(
aws_rhcos_push_item: AmiPushItem, aws_push_item: AmiPushItem
) -> List[AmiPushItem]:
return [aws_rhcos_push_item, aws_push_item]


@pytest.fixture
def pub_response_azure(vhd_push_item: VHDPushItem) -> List[VHDPushItem]:
return [vhd_push_item]


@pytest.fixture
def pub_response_diff_amis(
aws_push_item_2: AmiPushItem, aws_push_item: AmiPushItem
) -> List[AmiPushItem]:
return [aws_push_item, aws_push_item_2]


class BadPubResponse:
name: str
description: str
src: str

def __init__(self, name, description, src):
self.name = name
self.description = description
self.src = src


@pytest.fixture
def bad_pub_response() -> List[VHDPushItem]:
def bad_pub_response_vmi() -> List[BadPubResponse]:
params = {
"name": "vhd_pushitem",
"description": "fakevhd",
"src": "fake-src",
}
vhd_push_item = VHDPushItem(**params)
return [vhd_push_item, vhd_push_item]
return [BadPubResponse(**params), BadPubResponse(**params)]
Loading

0 comments on commit a7f1a9a

Please sign in to comment.