Last active
February 1, 2024 12:04
-
-
Save adoublef/6ebfbd0bd6acfff2702bddca0e67de0b to your computer and use it in GitHub Desktop.
Keto Testcontainers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package keto | |
import ( | |
"context" | |
"fmt" | |
"net" | |
"github.com/testcontainers/testcontainers-go" | |
) | |
type KetoContainer struct { | |
testcontainers.Container | |
} | |
func (c *KetoContainer) WriteAPIAddress(ctx context.Context) (string, error) { | |
containerPort, err := c.MappedPort(ctx, "4467/tcp") | |
if err != nil { | |
return "", err | |
} | |
host, err := c.Host(ctx) | |
if err != nil { | |
return "", err | |
} | |
connStr := fmt.Sprintf("http://%s", net.JoinHostPort(host, containerPort.Port())) | |
return connStr, nil | |
} | |
func (c *KetoContainer) ReadAPIAddress(ctx context.Context) (string, error) { | |
containerPort, err := c.MappedPort(ctx, "4466/tcp") | |
if err != nil { | |
return "", err | |
} | |
host, err := c.Host(ctx) | |
if err != nil { | |
return "", err | |
} | |
connStr := fmt.Sprintf("http://%s", net.JoinHostPort(host, containerPort.Port())) | |
return connStr, nil | |
} | |
func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*KetoContainer, error) { | |
req := testcontainers.ContainerRequest{ | |
Image: "oryd/keto:v0.11.1", | |
ExposedPorts: []string{"4466/tcp", "4467/tcp"}, | |
Cmd: []string{"serve"}, | |
Files: []testcontainers.ContainerFile{}, | |
} | |
genericContainerReq := testcontainers.GenericContainerRequest{ | |
ContainerRequest: req, | |
Started: true, | |
} | |
for _, opt := range opts { | |
opt.Customize(&genericContainerReq) | |
} | |
container, err := testcontainers.GenericContainer(ctx, genericContainerReq) | |
if err != nil { | |
return nil, err | |
} | |
return &KetoContainer{Container: container}, nil | |
} | |
func WithVolumeBind(host, target string, mode int64) testcontainers.CustomizeRequestOption { | |
return func(req *testcontainers.GenericContainerRequest) { | |
f := testcontainers.ContainerFile{ | |
HostFilePath: host, | |
ContainerFilePath: target, | |
FileMode: mode, | |
} | |
req.Files = append(req.Files, f) | |
} | |
} | |
func WithCommand(cmds ...string) testcontainers.CustomizeRequestOption { | |
return func(req *testcontainers.GenericContainerRequest) { | |
req.Cmd = append(req.Cmd, cmds...) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package keto | |
import ( | |
"context" | |
"testing" | |
ory "github.com/ory/client-go" | |
"github.com/testcontainers/testcontainers-go" | |
"github.com/testcontainers/testcontainers-go/wait" | |
) | |
func TestKeto(t *testing.T) { | |
ctx := context.Background() | |
container, err := RunContainer(ctx, | |
testcontainers.WithWaitStrategy(wait.ForHTTP("/health/ready").WithPort("4467")), | |
WithVolumeBind("./testdata/namespaces.ts", "/tmp/namespaces.ts", 0777), | |
WithVolumeBind("./testdata/keto.yml", "/tmp/keto.yml", 0777), | |
WithCommand("-c", "/tmp/keto.yml"), | |
) | |
if err != nil { | |
t.Fatal(err) | |
} | |
t.Cleanup(func() { | |
if err := container.Terminate(ctx); err != nil { | |
t.Fatalf("failed to terminate container: %s", err) | |
} | |
}) | |
// perform assertions | |
var namespace = "Blog" | |
var object = "secret_post" | |
var relation = "view" | |
var subjectId = "Bob" | |
payload := ory.CreateRelationshipBody{ | |
Namespace: &namespace, | |
Object: &object, | |
Relation: &relation, | |
SubjectId: &subjectId, | |
} | |
// write | |
url, err := container.WriteAPIAddress(ctx) | |
if err != nil { | |
t.Fatal(err) | |
} | |
cw := newTestClient(t, url) | |
_, _, err = cw.RelationshipAPI.CreateRelationship(ctx).CreateRelationshipBody(payload).Execute() | |
if err != nil { | |
t.Fatalf("relationship: %v", err) | |
} | |
// read | |
url, err = container.ReadAPIAddress(ctx) | |
if err != nil { | |
t.Fatal(err) | |
} | |
cr := newTestClient(t, url) | |
check, _, err := cr.PermissionAPI.CheckPermission(ctx). | |
Namespace(namespace). | |
Object(object). | |
Relation(relation). | |
SubjectId(subjectId).Execute() | |
if err != nil { | |
t.Fatalf("permission: %v", err) | |
} | |
if !check.Allowed { | |
t.Fatalf("should be allowed") | |
} | |
} | |
func newTestClient(t testing.TB, url string) *ory.APIClient { | |
c := ory.NewConfiguration() | |
c.Servers = []ory.ServerConfiguration{{URL: url}} | |
return ory.NewAPIClient(c) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment