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
20 changes: 14 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ on:
pull_request:
push:
branches: ["main"]
release:
types: [published]
tags:
- 'v*'

permissions:
contents: read
contents: write

jobs:
test:
Expand All @@ -34,19 +34,19 @@ jobs:
docker:
name: Build & Push Docker image (release only)
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'
if: startsWith(github.ref, 'refs/tags/')
steps:
- name: Checkout (release tag)
uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
ref: ${{ github.ref_name }}

- name: Set image tag (VERSION) from release tag
id: meta
shell: bash
run: |
set -euo pipefail
echo "version=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
echo "version=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand All @@ -72,3 +72,11 @@ jobs:
VERSION: ${{ steps.meta.outputs.version }}
run: |
echo "Pushed image: ${REGISTRY}/browser-ui:${VERSION}"

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ github.ref_name }}" \
--title "${{ github.ref_name }}" \
--generate-notes
47 changes: 35 additions & 12 deletions pkg/collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/alcounit/seleniferous/v2/pkg/store"
"github.com/alcounit/selenosis/v2/pkg/ipuuid"

browserv1 "github.com/alcounit/browser-controller/apis/browser/v1"
logctx "github.com/alcounit/browser-controller/pkg/log"
corev1 "k8s.io/api/core/v1"
)
Expand All @@ -34,6 +35,24 @@ func (c *Collector) Run(ctx context.Context) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

browsers, err := c.client.ListBrowsers(ctx, c.namespace)
if err != nil {
return err

}

for _, browser := range browsers {
sessionId, err := parseIp(browser.Status.PodIP)
if err != nil {
log.Error().Err(err).Str("sessionId", sessionId).Msgf("sessionId not found")
return errors.New("failed to convert IP to UUID")
}

storeSession(sessionId, browser, c)
log.Info().Str("sessionId", sessionId).Msg("add session to store")

}

stream, err := c.client.Events(ctx, c.namespace)
if err != nil {
return err
Expand Down Expand Up @@ -65,19 +84,10 @@ func (c *Collector) Run(ctx context.Context) error {
return errors.New("failed to convert IP to UUID")
}

sess := &types.Session{
SessionId: sessionId,
BrowserId: browserEvent.Browser.Name,
BrowserIP: browserEvent.Browser.Status.PodIP,
BrowserName: browserEvent.Browser.Spec.BrowserName,
BrowserVersion: browserEvent.Browser.Spec.BrowserVersion,
StartTime: browserEvent.Browser.CreationTimestamp.DeepCopy(),
Phase: corev1.PodPhase(browserEvent.Browser.Status.Phase),
}
eventType := strings.ToLower(string(browserEvent.EventType))
storeSession(sessionId, browserEvent.Browser, c)

c.store.Set(browserEvent.Browser.Name, sess)
log.Info().Str("eventType", eventType).Str("sessionId", sess.SessionId).Msg("add/update session in store")
eventType := strings.ToLower(string(browserEvent.EventType))
log.Info().Str("eventType", eventType).Str("sessionId", sessionId).Msg("add/update session in store")
continue
}

Expand All @@ -98,3 +108,16 @@ func parseIp(ip string) (string, error) {
return rawId.String(), err

}

func storeSession(sessionId string, browser *browserv1.Browser, c *Collector) {
sess := &types.Session{
SessionId: sessionId,
BrowserId: browser.Name,
BrowserIP: browser.Status.PodIP,
BrowserName: browser.Spec.BrowserName,
BrowserVersion: browser.Spec.BrowserVersion,
StartTime: browser.CreationTimestamp.DeepCopy(),
Phase: corev1.PodPhase(browser.Status.Phase),
}
c.store.Set(browser.Name, sess)
}
66 changes: 61 additions & 5 deletions pkg/collector/collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ func (s *fakeStream) Errors() <-chan error { return s.errorsCh }
func (s *fakeStream) Close() { s.closed = true }

type fakeClient struct {
stream *fakeStream
err error
stream *fakeStream
err error
browsers []*browserv1.Browser
listErr error
}

func (c *fakeClient) Events(ctx context.Context, namespace string, opts ...client.EventsOption) (client.BrowserEventStream, error) {
Expand All @@ -39,6 +41,10 @@ func (c *fakeClient) Events(ctx context.Context, namespace string, opts ...clien
return c.stream, nil
}

func (c *fakeClient) ListBrowsers(context.Context, string) ([]*browserv1.Browser, error) {
return c.browsers, c.listErr
}

func (c *fakeClient) CreateBrowser(context.Context, string, *browserv1.Browser) (*browserv1.Browser, error) {
panic("not used")
}
Expand All @@ -48,9 +54,6 @@ func (c *fakeClient) GetBrowser(context.Context, string, string) (*browserv1.Bro
func (c *fakeClient) DeleteBrowser(context.Context, string, string) error {
panic("not used")
}
func (c *fakeClient) ListBrowsers(context.Context, string) ([]*browserv1.Browser, error) {
panic("not used")
}

func newBrowserEvent(eventType event.EventType, name, podIP string) *event.BrowserEvent {
now := metav1.NewTime(time.Unix(0, 0).UTC())
Expand Down Expand Up @@ -176,6 +179,59 @@ func TestCollectorRunInvalidIP(t *testing.T) {
}
}

func TestCollectorRunListBrowsersError(t *testing.T) {
cl := &fakeClient{listErr: errors.New("list error")}
col := NewCollector(cl, "default", store.NewDefaultStore(), nil)

err := col.Run(context.Background())
if err == nil || err.Error() != "list error" {
t.Fatalf("expected list error, got %v", err)
}
}

func TestCollectorRunListBrowsersPopulatesStore(t *testing.T) {
stream := &fakeStream{
eventsCh: make(chan *event.BrowserEvent),
errorsCh: make(chan error),
}
close(stream.eventsCh)

now := metav1.NewTime(time.Unix(0, 0).UTC())
existing := &browserv1.Browser{
ObjectMeta: metav1.ObjectMeta{
Name: "browser-existing",
CreationTimestamp: now,
},
Spec: browserv1.BrowserSpec{
BrowserName: "chrome",
BrowserVersion: "123",
},
Status: browserv1.BrowserStatus{
PodIP: "127.0.0.1",
Phase: corev1.PodRunning,
},
}

st := store.NewDefaultStore()
cl := &fakeClient{stream: stream, browsers: []*browserv1.Browser{existing}}
col := NewCollector(cl, "default", st, nil)

col.Run(context.Background()) //nolint:errcheck

val, ok := st.Get("browser-existing")
if !ok {
t.Fatalf("expected browser-existing to be in store after ListBrowsers")
}
sess, ok := val.(*types.Session)
if !ok {
t.Fatalf("expected stored value to be *types.Session")
}
expectedID, _ := ipuuid.IPToUUID(net.ParseIP("127.0.0.1"))
if sess.SessionId != expectedID.String() {
t.Fatalf("expected sessionId %s, got %s", expectedID.String(), sess.SessionId)
}
}

func TestCollectorRunAddsSession(t *testing.T) {
stream := &fakeStream{
eventsCh: make(chan *event.BrowserEvent, 1),
Expand Down