Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/8292.doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add BEP-1038 for `ImageV2` GQL Implementation
99 changes: 99 additions & 0 deletions proposals/BEP-1038-image-v2-gql-implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
Author: Gyubong Lee ([email protected])
Status: Draft
Created: 2026-01-26
Created-Version: 26.2.0
Target-Version: 26.2.0
Implemented-Version:
---

# BEP-1038: ImageV2 GQL Implementation

Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the BEP Writing Guide (proposals/README.md line 58), BEP documents should include a "Related Issues" section that links to JIRA/GitHub issues. The PR description mentions BA-4036, but the BEP document itself lacks a "Related Issues" section. Consider adding this section to align with the BEP guidelines.

Suggested change
## Related Issues
- [BA-4036](https://jira.backend.ai/browse/BA-4036)

Copilot uses AI. Check for mistakes.
## Overview

This document defines the implementation plan for `ImageV2GQL` types as part of the Strawberry GraphQL migration (BEP-1010). It specifies:

1. **Types to Include** - Types that will be implemented
2. **Types to Defer** - Types requiring Node connections (implement later)

> **Note**: Enums are directly exposed from existing definitions. Mutations, Filters, and OrderBy types are out of scope for this BEP.

## Document Structure

| Document | Description |
|----------|-------------|
| [types-to-include.md](BEP-1038/types-to-include.md) | Detailed specifications of types to implement |
| [types-to-defer.md](BEP-1038/types-to-defer.md) | Types requiring Node connections |

## Summary

### Types to Include

#### Sub-Info Types (Leaf)
- `ImageTagEntryGQL` - Tag key-value pair
- `ImageLabelEntryGQL` - Label key-value pair
- `ImageResourceLimitGQL` - Resource limit info

#### Info Types (Grouped)
- `ImageIdentityInfoGQL` - Identity info (canonical_name, namespace, architecture, aliases)
- `ImageMetadataInfoGQL` - Metadata info (tags, labels, digest, size_bytes, status, created_at)
- `ImageRequirementsInfoGQL` - Requirements info (resource_limits, supported_accelerators)
- `ImagePermissionInfoGQL` - Permission info (permissions)

#### Main Types
- `ImageV2GQL` - Main image node type
- `ImageEdgeGQL` - Edge type
- `ImageConnectionV2GQL` - Connection type

### Types to Defer (Node Connections)

| Type/Field | Future Node | Action |
|------------|-------------|--------|
| `ImageV2GQL.registry` | `ContainerRegistryNode` | Return primitive string for now |

## Type Structure

```
ImageV2GQL
├── id: NodeID[UUID]
├── identity: ImageIdentityInfoGQL # Image identity information
│ ├── canonical_name
│ ├── namespace
│ ├── architecture
│ └── aliases
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I mentioned yesterday, aliases should also be passed as direct fields of ImageV2 via connections or nodes.

├── metadata: ImageMetadataInfoGQL # Metadata information
│ ├── tags
│ ├── labels
│ ├── digest
│ ├── size_bytes
│ ├── status
│ └── created_at
├── requirements: ImageRequirementsInfoGQL # Runtime requirements
│ ├── resource_limits
│ └── supported_accelerators
├── permission: ImagePermissionInfoGQL # RBAC permissions
│ └── permissions
├── registry_id: UUID # Registry ID (for direct query)
└── registry: ContainerRegistryNode # (deferred)
```

## Implementation Checklist

### PR Scope

- [ ] Implement all types listed in "Types to Include"
- [ ] Implement connection resolver with pagination

### Future PRs

- [ ] ContainerRegistryNode PR: Replace `registry` string with connection

## References

- [BEP-1010: GraphQL API Migration to Strawberry](BEP-1010-new-gql.md)
- [BEP-1034: KernelV2 GQL Implementation](BEP-1034-kernel-v2-gql-implementation.md)
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reference to BEP-1034 points to a non-existent file. While BEP-1034 is listed in the proposals/README.md, the file proposals/BEP-1034-kernel-v2-gql-implementation.md does not exist yet. Consider either removing this reference until BEP-1034 is created, or ensuring the referenced file exists before this PR is merged.

Suggested change
- [BEP-1034: KernelV2 GQL Implementation](BEP-1034-kernel-v2-gql-implementation.md)

Copilot uses AI. Check for mistakes.
48 changes: 48 additions & 0 deletions proposals/BEP-1038/types-to-defer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# ImageV2 GQL - Types to Defer

These types reference entities that should be represented as proper Relay Node connections. Since the corresponding Node types are not yet implemented, these fields/types should be **omitted** or use primitive types and added later.

---

## Summary

| Type/Field | Future Node | Current Action |
|------------|-------------|----------------|
| `ImageV2GQL.registry` | `ContainerRegistryNode` | Keep as string, replace later |

---

## Registry Types (Defer to ContainerRegistryNode)

### ImageV2GQL.registry field

**Current Action**: Keep as primitive `str` type.

**Future**: Replace with `ContainerRegistryNode` connection.

The `ContainerRegistryNode` will include:
- `is_local`: Whether the registry is local
- `project`: Project/namespace in the registry

```python
# Current implementation
@strawberry.type(name="ImageV2")
class ImageV2GQL(Node):
registry: str # Keep as string for now

# Future implementation (after ContainerRegistryNode PR)
@strawberry.type(name="ImageV2")
class ImageV2GQL(Node):
@strawberry.field
async def registry(self, info: strawberry.Info) -> ContainerRegistryNode | None:
# Load via dataloader
...
```

---

## Future Implementation PRs

| PR | Fields to Add/Modify |
|----|---------------------|
| ContainerRegistryNode PR | Replace `registry: str` with `registry: ContainerRegistryNode` connection |
112 changes: 112 additions & 0 deletions proposals/BEP-1038/types-to-include.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# ImageV2 GQL - Types to Include

This document lists all types to be implemented with their fields.

> **Note**: Enums (`ImageStatusGQL`, `ImagePermissionGQL`) are directly exposed from existing definitions. Mutations, Filters, and OrderBy types are out of scope for this BEP.

---

## Sub-Info Types

### ImageTagEntryGQL
```python
@strawberry.type(name="ImageTagEntry")
class ImageTagEntryGQL:
key: str
value: str
```

### ImageLabelEntryGQL
```python
@strawberry.type(name="ImageLabelEntry")
class ImageLabelEntryGQL:
key: str
value: str
```

### ImageResourceLimitGQL
```python
@strawberry.type(name="ImageResourceLimit")
class ImageResourceLimitGQL:
key: str
min: str
max: str | None
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type hints use PEP 604 union syntax (str | None) and PEP 585 generics (list[str]), which require Python 3.10+. However, BEP-1010 specifies Python 3.9+ as the runtime environment. For Python 3.9 compatibility, use Optional[str] from typing instead of str | None, and List[str] instead of list[str]. If the project has moved to Python 3.10+ as the minimum version, this should be documented in BEP-1010.

Copilot uses AI. Check for mistakes.
```

---

## Info Types

### ImageIdentityInfoGQL
```python
@strawberry.type(name="ImageIdentityInfo")
class ImageIdentityInfoGQL:
canonical_name: str # Full canonical name (e.g., cr.backend.ai/stable/python:3.9)
namespace: str # Base image namespace (e.g., python)
architecture: str # CPU architecture (e.g., x86_64, aarch64)
aliases: list[str] # Image aliases
```

### ImageMetadataInfoGQL
```python
@strawberry.type(name="ImageMetadataInfo")
class ImageMetadataInfoGQL:
# Manifest info
tags: list[ImageTagEntryGQL] # Parsed tag components (e.g., 3.9, ubuntu20.04)
labels: list[ImageLabelEntryGQL] # Docker labels
digest: str | None # Config digest (image hash)
size_bytes: int # Image size in bytes

# Lifecycle info
status: ImageStatusGQL # ALIVE, DELETED
created_at: datetime | None
```

### ImageRequirementsInfoGQL
```python
@strawberry.type(name="ImageRequirementsInfo")
class ImageRequirementsInfoGQL:
resource_limits: list[ImageResourceLimitGQL]
supported_accelerators: list[str]
```

### ImagePermissionInfoGQL
```python
@strawberry.type(name="ImagePermissionInfo")
class ImagePermissionInfoGQL:
permissions: list[ImagePermissionGQL]
```

---

## Main Types

### ImageV2GQL

```python
@strawberry.type(name="ImageV2")
class ImageV2GQL(Node):
id: NodeID[UUID]

# Sub-info types
identity: ImageIdentityInfoGQL
metadata: ImageMetadataInfoGQL
requirements: ImageRequirementsInfoGQL
permission: ImagePermissionInfoGQL | None

# Registry
registry_id: UUID # For direct query without loading full registry node
# registry: ContainerRegistryNode connection to be added later
```

### ImageEdgeGQL
```python
ImageEdgeGQL = Edge[ImageV2GQL]
```

### ImageConnectionV2GQL
```python
@strawberry.type(name="ImageConnectionV2")
class ImageConnectionV2GQL(Connection[ImageV2GQL]):
count: int
```
Loading