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
31 changes: 18 additions & 13 deletions crossview-go-server/services/kubernetes_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"

"crossview-go-server/lib"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand Down Expand Up @@ -36,19 +37,23 @@ func (k *KubernetesService) GetResources(apiVersion, kind, namespace, contextNam
return nil, fmt.Errorf("apiVersion is required")
}

apiVersionParts := strings.Split(apiVersion, "/")
if len(apiVersionParts) != 2 {
return nil, fmt.Errorf("invalid apiVersion format: %s, expected group/version", apiVersion)
}

group := strings.TrimSpace(apiVersionParts[0])
version := strings.TrimSpace(apiVersionParts[1])

if group == "" {
return nil, fmt.Errorf("invalid apiVersion format: %s, group is required", apiVersion)
}
if version == "" {
return nil, fmt.Errorf("invalid apiVersion format: %s, version is required", apiVersion)
var group, version string
if apiVersion == "v1" {
group = ""
version = "v1"
} else {
apiVersionParts := strings.Split(apiVersion, "/")
if len(apiVersionParts) != 2 {
return nil, fmt.Errorf("invalid apiVersion format: %s, expected group/version or v1", apiVersion)
}
group = strings.TrimSpace(apiVersionParts[0])
version = strings.TrimSpace(apiVersionParts[1])
if group == "" {
return nil, fmt.Errorf("invalid apiVersion format: %s, group is required", apiVersion)
}
if version == "" {
return nil, fmt.Errorf("invalid apiVersion format: %s, version is required", apiVersion)
}
}

if plural == "" {
Expand Down
15 changes: 15 additions & 0 deletions k8s/crossplane-example/ManagedResourceDefinition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: ManagedResourceDefinition
metadata:
name: example-mrd
spec:
group: example.crossplane.io
names:
kind: ExampleResource
plural: exampleresources
singular: exampleresource
scope: Cluster
versions:
- name: v1alpha1
served: true
storage: true
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ export class GetManagedResourceActivationPoliciesUseCase {

async execute(context = null) {
try {
const managedResourcesResult = await this.kubernetesRepository.getManagedResources(context);
const allResources = managedResourcesResult.items || [];

const mraps = allResources.filter(item => item.kind === 'ManagedResourceActivationPolicy');
const apiVersion = 'apiextensions.crossplane.io/v1alpha1';
const kind = 'ManagedResourceActivationPolicy';
const mrapsResult = await this.kubernetesRepository.getResources(apiVersion, kind, null, context);
const mraps = mrapsResult.items || mrapsResult; // Support both new format and legacy array format
const mrapsArray = Array.isArray(mraps) ? mraps : [];

return mrapsArray.map(mrap => ({
name: mrap.metadata?.name || 'unknown',
namespace: mrap.metadata?.namespace || null,
Expand Down
9 changes: 4 additions & 5 deletions src/domain/usecases/GetManagedResourceDefinitionsUseCase.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ export class GetManagedResourceDefinitionsUseCase {

async execute(context = null) {
try {
const managedResourcesResult = await this.kubernetesRepository.getManagedResources(context);
const allResources = managedResourcesResult.items || [];

const mrds = allResources.filter(item => item.kind === 'ManagedResourceDefinition');
const apiVersion = 'apiextensions.crossplane.io/v1alpha1';
const kind = 'ManagedResourceDefinition';
const mrdsResult = await this.kubernetesRepository.getResources(apiVersion, kind, null, context);
const mrds = mrdsResult.items || mrdsResult; // Support both new format and legacy array format
const mrdsArray = Array.isArray(mrds) ? mrds : [];

return mrdsArray.map(mrd => {
const conditions = mrd.status?.conditions || [];
const establishedCondition = conditions.find(c => c.type === 'Established');
Expand Down
14 changes: 4 additions & 10 deletions src/presentation/components/common/ResourceDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ export const ResourceDetails = ({ resource, onClose, onNavigate, onBack }) => {
const { addResource, removeResource, watchedResources } = useOnWatchResources();
const [activeTab, setActiveTab] = useState('overview');

// Use the custom hook for resource data loading
const { loading, fullResource, relatedResources, events, eventsLoading } = useResourceData(resource);

const getResourceKey = (res) => {
return `${res.apiVersion || ''}:${res.kind || ''}:${res.metadata?.namespace || ''}:${res.metadata?.name || ''}`;
};

// Check if resource is watched - use both current resource and fullResource
const currentResource = fullResource || resource;
const resourceKey = currentResource ? getResourceKey(currentResource) : null;
const watchedResource = resourceKey ? watchedResources.find(r => {
Expand All @@ -41,11 +39,9 @@ export const ResourceDetails = ({ resource, onClose, onNavigate, onBack }) => {

const handleWatchToggle = () => {
if (isWatched && watchedResource) {
// Unwatch the resource - use _key if available, otherwise calculate it
const keyToRemove = watchedResource._key || getResourceKey(watchedResource);
removeResource(keyToRemove);
} else {
// Watch the resource
const resourceToAdd = fullResource || resource;
if (resourceToAdd) {
const resourceWithPlural = {
Expand All @@ -60,14 +56,13 @@ export const ResourceDetails = ({ resource, onClose, onNavigate, onBack }) => {
if (!resource) return null;

const handleRelatedClick = (related) => {
// Ensure namespace is null (not "undefined" string) for cluster-scoped resources
const namespace = related.namespace && related.namespace !== 'undefined' && related.namespace !== 'null' ? related.namespace : null;
onNavigate({
apiVersion: related.apiVersion,
kind: related.kind,
name: related.name,
namespace: namespace,
plural: related.plural || null, // Include plural if available
plural: related.plural || null,
});
};

Expand Down Expand Up @@ -157,7 +152,6 @@ export const ResourceDetails = ({ resource, onClose, onNavigate, onBack }) => {
</Box>
) : (
<Box display="flex" flexDirection="column">
{/* Tabs Navigation */}
<Box px={4} pt={4} flexShrink={0}>
<ResourceTabs
activeTab={activeTab}
Expand Down Expand Up @@ -189,7 +183,6 @@ export const ResourceDetails = ({ resource, onClose, onNavigate, onBack }) => {
/>
</Box>

{/* Tab Content */}
<Box flex={1} minH={0}>
{activeTab === 'overview' && (
<ResourceOverview
Expand All @@ -208,9 +201,10 @@ export const ResourceDetails = ({ resource, onClose, onNavigate, onBack }) => {

{activeTab === 'relations' && (
<ResourceRelations
resource={resource}
resource={fullResource || resource}
relatedResources={relatedResources}
colorMode={colorMode}
colorMode={colorMode}
onNavigate={handleRelatedClick}
/>
)}
</Box>
Expand Down
Loading
Loading