Skip to content

PoC for nebi remote interface #555

Description

@pmeier

nebi currently treats a server different from an OCI registry. Part of the UX rework is to make them peers in terms of the functionality a nebi instance that connects to them. Here is an example interface

import "errors"

type AuthenticationCredentialType string

type AuthenticationCredential struct {
	Type     AuthenticationCredentialType
	Username string                  
	Password string             
	Token    string                     
}

func (ac *AuthenticationCredential) Validate() error {
	switch ac.Type {
	case BasicAuthenticationCredentialType:
		if ac.Username == "" || ac.Password == "" {
			return errors.New("basic auth requires username and password")
		}
	case TokenAuthenticationCredentialType:
		if ac.Token == "" {
			return errors.New("token auth requires token")
		}
	default:
		return errors.New("unknown auth type")
	}
	return nil
}

const (
	BasicAuthenticationCredentialType = "basic"
	TokenAuthenticationCredentialType = "token"
)

type WorkspacePreview struct {
	ID      string
	Name    string
	Version uint
}

type Workspace struct {
	WorkspacePreview
	Data any
}

type Remote interface {
	SupportedAuthentication() []AuthenticationCredentialType
	Authenticate(ac AuthenticationCredential) error
	List() ([]WorkspacePreview, error)
	Pull(id string) (Workspace, error)
	Push(Workspace) error
}
  1. SupportedAuthentication() []AuthenticationCredentialType is used for the client to know which authentication methods to offer to the user. If empty, the client can assume that no authentication is required. That is true for example for public, read-only OCI registries.
  2. Authenticate(ac AuthenticationCredential) error is used for the initial authentication. If an error is returned, the client should refuse to add the remote.
  3. List() ([]WorkspacePreview, error) list all workspaces that the authenticated user has access to. Error if the user is not authenticated.
  4. Pull(id string) (Workspace, error) pulls a workspace from the remote. Error if the user is not authenticated or the workspace doesn't exist or the user has no permissions to read it.
  5. Push(Workspace) error pushes a new workspace or a new version to the remote. Error if the user is not authenticated, if the user has no write permissions, or if the push would result in a conflicting state (user tries to push version 18, but 18 already exists on the remote). Conflict resolution is out of scope for now.

In the example above WorkspacePreview and Workspace are just placeholders and need to be filled with the actual fields. We also probably should have some custom error types so the client can better react to the different error reasons.

Important: This is exploratory work. It can happen as part of the current code base, or it can happen alongside it. Whatever is easier. Goal is to find out whether the interface above is sufficient for a client (CLI, web UI with NEBI_MODE=local) to interact with an arbitrary remote and whether the remotes are able to implement the interface. This can be achieved for example by implementing a type OCIRemote struct {} that implements the Remote interface and is demonstrated to work.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

Priority

None yet

Start date

None yet

Target date

None yet

Size

S

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions