Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
SimoneDutto committed Sep 3, 2024
1 parent 8766152 commit b795e92
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 0 deletions.
105 changes: 105 additions & 0 deletions internal/db/resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2024 Canonical.
package db

import (
"context"
"database/sql"

"github.com/canonical/jimm/v3/internal/errors"
"github.com/canonical/jimm/v3/internal/servermon"
)

const MUTIPLE_PAGE_SQL = `
(
SELECT 'controller' AS type,
uuid AS id,
name AS name,
'' AS parent_id,
'' AS parent_name,
'' AS parent_type
FROM controllers
)
UNION
(
SELECT 'model' AS type,
models.uuid AS id,
models.name AS name,
controllers.uuid AS parent_id,
controllers.name AS parent_name,
'controller' AS parent_type
FROM models
JOIN controllers ON models.controller_id = controllers.id
)
UNION
(
SELECT 'application_offer' AS type,
application_offers.uuid AS id,
application_offers.name AS name,
models.uuid AS parent_id,
models.name AS parent_name,
'model' AS parent_type
FROM application_offers
JOIN models ON application_offers.model_id = models.id
)
UNION
(
SELECT 'cloud' AS type,
clouds.name AS id,
clouds.name AS name,
'' AS parent_id,
'' AS parent_name,
'' AS parent_type
FROM clouds
)
UNION
(
SELECT 'service_account' AS type,
identities.name AS id,
identities.name AS name,
'' AS parent_id,
'' AS parent_name,
'' AS parent_type
FROM identities
WHERE name NOT LIKE '%@%'
)
ORDER BY id
OFFSET ?
LIMIT ?;
`

type Resource struct {
Type string
UUID sql.NullString
Name string
ParentId sql.NullString
ParentName string
ParentType string
}

func (d *Database) GetResources(ctx context.Context, limit, offset int) (_ []Resource, err error) {
const op = errors.Op("db.GetMultipleModels")
if err := d.ready(); err != nil {
return nil, errors.E(op, err)
}

durationObserver := servermon.DurationObserver(servermon.DBQueryDurationHistogram, string(op))
defer durationObserver()
defer servermon.ErrorCounter(servermon.DBQueryErrorCount, &err, string(op))

db := d.DB.WithContext(ctx)
rows, err := db.Raw(MUTIPLE_PAGE_SQL, offset, limit).Rows()
if err != nil {
return nil, err
}
defer rows.Close()
resources := make([]Resource, 0)
for rows.Next() {
var res Resource
err := db.ScanRows(rows, &res)
if err != nil {
return nil, err
}
resources = append(resources, res)
}
return resources, nil
}
81 changes: 81 additions & 0 deletions internal/db/resources_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2024 Canonical.
package db_test

import (
"context"
"database/sql"

qt "github.com/frankban/quicktest"
"github.com/juju/juju/state"

"github.com/canonical/jimm/v3/internal/db"
"github.com/canonical/jimm/v3/internal/dbmodel"
)

func (s *dbSuite) Setup(c *qt.C) {
err := s.Database.Migrate(context.Background(), true)
c.Assert(err, qt.Equals, nil)

u, err := dbmodel.NewIdentity("[email protected]")
c.Assert(err, qt.IsNil)
c.Assert(s.Database.DB.Create(&u).Error, qt.IsNil)

cloud := dbmodel.Cloud{
Name: "test-cloud",
Type: "test-provider",
Regions: []dbmodel.CloudRegion{{
Name: "test-region",
}},
}
c.Assert(s.Database.DB.Create(&cloud).Error, qt.IsNil)

cred := dbmodel.CloudCredential{
Name: "test-cred",
Cloud: cloud,
Owner: *u,
AuthType: "empty",
}
c.Assert(s.Database.DB.Create(&cred).Error, qt.IsNil)

controller := dbmodel.Controller{
Name: "test-controller",
UUID: "00000000-0000-0000-0000-0000-0000000000001",
CloudName: "test-cloud",
CloudRegion: "test-region",
}
err = s.Database.AddController(context.Background(), &controller)
c.Assert(err, qt.Equals, nil)

model := dbmodel.Model{
Name: "test-model-1",
UUID: sql.NullString{
String: "00000001-0000-0000-0000-0000-000000000001",
Valid: true,
},
OwnerIdentityName: u.Name,
ControllerID: controller.ID,
CloudRegionID: cloud.Regions[0].ID,
CloudCredentialID: cred.ID,
Type: "iaas",
DefaultSeries: "warty",
Life: state.Alive.String(),
Status: dbmodel.Status{
Status: "available",
Since: db.Now(),
},
SLA: dbmodel.SLA{
Level: "unsupported",
},
}
err = s.Database.AddModel(context.Background(), &model)
c.Assert(err, qt.Equals, nil)
}

func (s *dbSuite) TestGetResources(c *qt.C) {
// create one model, one controller, one cloud
s.Setup(c)
ctx := context.Background()
res, err := s.Database.GetResources(ctx, 10, 0)
c.Assert(err, qt.Equals, nil)
c.Assert(res, qt.HasLen, 3)
}
1 change: 1 addition & 0 deletions internal/rebac_admin/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func SetupBackend(ctx context.Context, jimm jujuapi.JIMM) (*rebac_handlers.ReBAC
Entitlements: newEntitlementService(),
Groups: newGroupService(jimm),
Identities: newidentitiesService(jimm),
Resources: newResourcesService(jimm),
})
if err != nil {
zapctx.Error(ctx, "failed to create rebac admin backend", zap.Error(err))
Expand Down
32 changes: 32 additions & 0 deletions internal/rebac_admin/resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2024 Canonical.

package rebac_admin

import (
"context"

"github.com/canonical/rebac-admin-ui-handlers/v1/resources"

"github.com/canonical/jimm/v3/internal/jujuapi"
"github.com/canonical/jimm/v3/internal/rebac_admin/utils"
)

// resourcesService implements the `resourcesService` interface.
type resourcesService struct {
jimm jujuapi.JIMM
}

func newResourcesService(jimm jujuapi.JIMM) *resourcesService {
return &resourcesService{
jimm: jimm,
}
}

// resourcesService defines an abstract backend to handle Resources related operations.
func (s *resourcesService) ListResources(ctx context.Context, params *resources.GetResourcesParams) (*resources.PaginatedResponse[resources.Resource], error) {
_, err := utils.GetUserFromContext(ctx)
if err != nil {
return nil, err
}
return nil, nil
}

0 comments on commit b795e92

Please sign in to comment.