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
2 changes: 2 additions & 0 deletions cmd/agent/executor_agent_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ func (e *ExecutorAgentService) processAction(action actions.Action) {
tracker.Failed()
return
}
tracker.Running()

// Get executor
executor := e.GetExecutor(target.AccountID)
Expand Down Expand Up @@ -275,6 +276,7 @@ func (e *ExecutorAgentService) processScanAction(action actions.Action, tracker
tracker.Failed()
return
}
tracker.Running()

target := action.GetTarget()

Expand Down
2 changes: 1 addition & 1 deletion console/src/api/data-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export interface ActionResponseApi {
}

export interface ActionTargetApi {
accountName?: string;
accountId?: string;
clusterId?: string;
instances?: string[];
region?: string;
Expand Down
6 changes: 2 additions & 4 deletions console/src/app/Contexts/UserContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ export const UserProvider: React.FC<{ children: React.ReactNode }> = ({ children
fetch(window.location.href)
.then(response => {
const email = response.headers.get('gap-auth');
if (email) {
setUserEmail(email);
console.log('User email:', email);
}
setUserEmail(email || 'clusteriq@dev');
console.log('User email:', email || 'clusteriq@dev (fallback)');
})
.catch(error => console.error('Error fetching headers:', error));
}, []);
Expand Down
36 changes: 14 additions & 22 deletions console/src/app/Overview/hooks/useDashboardData.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
import { useState, useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';
import { api, OverviewSummaryApi } from '@api';

export const useDashboardData = () => {
const [inventoryData, setInventoryData] = useState<OverviewSummaryApi | undefined>();
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const { data, isLoading, error } = useQuery<OverviewSummaryApi>({
queryKey: ['overview'],
queryFn: async ({ signal }) => {
const { data } = await api.overview.overviewList({ signal });
return data;
},
refetchInterval: 5_000,
});

useEffect(() => {
const inventoryOverview = async () => {
try {
setLoading(true);
setError(null);
const { data } = await api.overview.overviewList();
setInventoryData(data);
} catch {
setError('Failed to fetch inventory data');
console.error('Failed to fetch inventory data.');
} finally {
setLoading(false);
}
};
inventoryOverview();
}, []);

return { inventoryData, loading, error };
return {
inventoryData: data,
loading: isLoading,
error: error ? 'Failed to fetch inventory data' : null,
};
};
39 changes: 14 additions & 25 deletions console/src/app/Overview/hooks/useEventsData.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,19 @@
import { useState, useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';
import { api, SystemEventResponseApi } from '@api';

export const useEventsData = () => {
const [events, setEvents] = useState<SystemEventResponseApi[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const { data, isLoading, error } = useQuery<SystemEventResponseApi[]>({
queryKey: ['recentEvents'],
queryFn: async ({ signal }) => {
const { data } = await api.events.eventsList({ page: 1, page_size: 10 }, { signal });
return data.items || [];
},
refetchInterval: 5_000,
});

useEffect(() => {
const fetchEvents = async () => {
try {
setLoading(true);
setError(null);
console.log('Fetching recent events...');
const { data } = await api.events.eventsList({ page: 1, page_size: 10 });
console.log('Events data received:', data);
setEvents(data.items || []);
} catch (err) {
setError('Failed to fetch events');
console.error('Error fetching events:', err);
} finally {
setLoading(false);
}
};

fetchEvents();
}, []);

return { events, loading, error };
return {
events: data || [],
loading: isLoading,
error: error ? 'Failed to fetch events' : null,
};
};
1 change: 1 addition & 0 deletions console/src/app/hooks/useAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export function useAccounts() {
const { data } = await api.accounts.accountsList({ page: 1, page_size: 10000 }, { signal });
return data.items || [];
},
refetchInterval: 10_000,
});
}
1 change: 1 addition & 0 deletions console/src/app/hooks/useClusters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export function useClusters() {
const { data } = await api.clusters.clustersList({ page: 1, page_size: 100000 }, { signal });
return data.items || [];
},
refetchInterval: 10_000,
});
}
1 change: 1 addition & 0 deletions console/src/app/hooks/useEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export function useEvents() {
const { data } = await api.events.eventsList({}, { signal });
return data.items || [];
},
refetchInterval: 5_000,
});
}
1 change: 1 addition & 0 deletions console/src/app/hooks/useInstances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export function useInstances() {
const { data } = await api.instances.instancesList({ page: 1, page_size: 100000 }, { signal });
return data.items || [];
},
refetchInterval: 10_000,
});
}
1 change: 1 addition & 0 deletions console/src/app/hooks/useScheduleActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function useScheduleActions() {
const { data } = await api.schedule.scheduleList({ page: 1, page_size: 10000 }, { signal });
return data.items || [];
},
refetchInterval: 5_000,
});
}

Expand Down
9 changes: 9 additions & 0 deletions internal/events/event_service/event_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const (
ResultSuccess = "Success"
ResultFailed = "Failed"
ResultPending = "Pending"
ResultRunning = "Running"
)

// Event severity levels
Expand Down Expand Up @@ -104,6 +105,14 @@ type EventTracker struct {
logger *zap.Logger
}

// Running marks the tracked event as in progress.
// Uses context.Background() as event updates happen asynchronously.
func (t *EventTracker) Running() {
if err := t.service.UpdateEventStatus(context.Background(), t.eventID, ResultRunning); err != nil {
t.logger.Error("Failed to update event status", zap.Error(err))
}
}

// Success marks the tracked event status as success.
// Uses context.Background() as event updates happen asynchronously.
func (t *EventTracker) Success() {
Expand Down
34 changes: 33 additions & 1 deletion internal/events/event_service/event_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,14 +255,46 @@ func testStartTracking_LogEventError(t *testing.T) {
assert.Nil(t, tracker)
}

// TestEventTracker verifies EventTracker updates status to Success/Failed and handles repo errors.
// TestEventTracker verifies EventTracker updates status to Running/Success/Failed and handles repo errors.
func TestEventTracker(t *testing.T) {
t.Run("Tracker Running update ok", func(t *testing.T) { testEventTracker_Running_OK(t) })
t.Run("Tracker Running update error", func(t *testing.T) { testEventTracker_Running_Error(t) })
t.Run("Tracker Success update ok", func(t *testing.T) { testEventTracker_Success_OK(t) })
t.Run("Tracker Success update error", func(t *testing.T) { testEventTracker_Success_Error(t) })
t.Run("Tracker Failed update ok", func(t *testing.T) { testEventTracker_Failed_OK(t) })
t.Run("Tracker Failed update error", func(t *testing.T) { testEventTracker_Failed_Error(t) })
}

func testEventTracker_Running_OK(t *testing.T) {
repo := &mockEventRepo{
updateEventStatusFn: func(ctx context.Context, eventID int64, result string) error {
return nil
},
}

svc := &EventService{repo: repo, logger: zap.NewNop()}
tracker := &EventTracker{eventID: 1, service: svc, logger: zap.NewNop()}

assert.NotPanics(t, func() { tracker.Running() })
assert.Equal(t, 1, repo.updateEventStatusCalls)
assert.Equal(t, ResultRunning, repo.lastUpdateStatusResult)
}

func testEventTracker_Running_Error(t *testing.T) {
repo := &mockEventRepo{
updateEventStatusFn: func(ctx context.Context, eventID int64, result string) error {
return errTest
},
}

svc := &EventService{repo: repo, logger: zap.NewNop()}
tracker := &EventTracker{eventID: 1, service: svc, logger: zap.NewNop()}

assert.NotPanics(t, func() { tracker.Running() })
assert.Equal(t, 1, repo.updateEventStatusCalls)
assert.Equal(t, ResultRunning, repo.lastUpdateStatusResult)
}

func testEventTracker_Success_OK(t *testing.T) {
repo := &mockEventRepo{
updateEventStatusFn: func(ctx context.Context, eventID int64, result string) error {
Expand Down
8 changes: 4 additions & 4 deletions internal/models/dto/scheduled_action_dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import "time"

// ActionTarget represents the target resource information for an action.
type ActionTarget struct {
AccountName string `json:"accountName"`
Region string `json:"region"`
ClusterID string `json:"clusterId"`
Instances []string `json:"instances"`
AccountID string `json:"accountId"`
Region string `json:"region"`
ClusterID string `json:"clusterId"`
Instances []string `json:"instances"`
} // @name ActionTarget

// ScheduledAction represents the data transfer object for a scheduled action.
Expand Down
Loading