Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement environment update functionality in launchdevly ui #423

Merged
merged 7 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
21 changes: 20 additions & 1 deletion internal/dev_server/adapters/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"net/url"
"strconv"

ldapi "github.com/launchdarkly/api-client-go/v14"
"github.com/pkg/errors"

ldapi "github.com/launchdarkly/api-client-go/v14"
)

const ctxKeyApi = ctxKey("adapters.api")
Expand All @@ -24,6 +25,7 @@ func GetApi(ctx context.Context) Api {
type Api interface {
GetSdkKey(ctx context.Context, projectKey, environmentKey string) (string, error)
GetAllFlags(ctx context.Context, projectKey string) ([]ldapi.FeatureFlag, error)
GetProjectEnvironments(ctx context.Context, projectKey string) ([]ldapi.Environment, error)
}

type apiClientApi struct {
Expand Down Expand Up @@ -52,6 +54,15 @@ func (a apiClientApi) GetAllFlags(ctx context.Context, projectKey string) ([]lda
return flags, err
}

func (a apiClientApi) GetProjectEnvironments(ctx context.Context, projectKey string) ([]ldapi.Environment, error) {
log.Printf("Fetching all environments for project '%s'", projectKey)
environments, err := a.getEnvironments(ctx, projectKey)
if err != nil {
err = errors.Wrap(err, "unable to get environments from LD API")
}
return environments, err
}

func (a apiClientApi) getFlags(ctx context.Context, projectKey string, href *string) ([]ldapi.FeatureFlag, error) {
var featureFlags *ldapi.FeatureFlags
var err error
Expand Down Expand Up @@ -87,6 +98,14 @@ func (a apiClientApi) getFlags(ctx context.Context, projectKey string, href *str
return flags, nil
}

func (a apiClientApi) getEnvironments(ctx context.Context, projectKey string) ([]ldapi.Environment, error) {
cdelst marked this conversation as resolved.
Show resolved Hide resolved
environments, _, err := a.apiClient.EnvironmentsApi.GetEnvironmentsByProject(ctx, projectKey).Limit(1000).Execute()
if err != nil {
return nil, err
}
return environments.Items, nil
}

func parseHref(href string) (limit, offset int64, err error) {
parsedUrl, err := url.Parse(href)
if err != nil {
Expand Down
15 changes: 15 additions & 0 deletions internal/dev_server/adapters/mocks/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions internal/dev_server/api/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,27 @@ paths:
description: OK. override removed
404:
description: no matching override found
/dev/projects/{projectKey}/environments:
get:
operationId: getProjectsEnvironments
summary: list all environments for the given project
parameters:
- $ref: "#/components/parameters/projectKey"
responses:
200:
description: OK. List of environments
content:
application/json:
schema:
description: list of environments
type: array
items:
$ref: "#/components/schemas/Environment"
uniqueItems: true
404:
$ref: "#/components/responses/ErrorResponse"
400:
$ref: "#/components/responses/ErrorResponse"
components:
parameters:
flagKey:
Expand Down Expand Up @@ -224,6 +245,17 @@ components:
type: integer
x-go-type: int64
description: unix timestamp for the lat time the flag values were synced from the source environment
Environment:
description: Environment
type: object
required:
- key
- name
properties:
key:
type: string
name:
type: string
responses:
FlagOverride:
description: Flag override
Expand Down
107 changes: 107 additions & 0 deletions internal/dev_server/api/server.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 39 additions & 11 deletions internal/dev_server/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ import (
)

//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config oapi-codegen-cfg.yaml api.yaml
type Server struct {
var _ StrictServerInterface = server{}
cdelst marked this conversation as resolved.
Show resolved Hide resolved

type server struct {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be private

}

func NewStrictServer() Server {
return Server{}
func NewStrictServer() StrictServerInterface {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we want to return the interface not the struct

return server{}
}

func (s Server) GetDevProjects(ctx context.Context, request GetDevProjectsRequestObject) (GetDevProjectsResponseObject, error) {
func (s server) GetDevProjects(ctx context.Context, request GetDevProjectsRequestObject) (GetDevProjectsResponseObject, error) {
store := model.StoreFromContext(ctx)
projectKeys, err := store.GetDevProjectKeys(ctx)
if err != nil {
Expand All @@ -27,7 +29,7 @@ func (s Server) GetDevProjects(ctx context.Context, request GetDevProjectsReques
return GetDevProjects200JSONResponse(projectKeys), nil
}

func (s Server) DeleteDevProjectsProjectKey(ctx context.Context, request DeleteDevProjectsProjectKeyRequestObject) (DeleteDevProjectsProjectKeyResponseObject, error) {
func (s server) DeleteDevProjectsProjectKey(ctx context.Context, request DeleteDevProjectsProjectKeyRequestObject) (DeleteDevProjectsProjectKeyResponseObject, error) {
store := model.StoreFromContext(ctx)
deleted, err := store.DeleteDevProject(ctx, request.ProjectKey)
if err != nil {
Expand All @@ -42,7 +44,7 @@ func (s Server) DeleteDevProjectsProjectKey(ctx context.Context, request DeleteD
return DeleteDevProjectsProjectKey204Response{}, nil
}

func (s Server) GetDevProjectsProjectKey(ctx context.Context, request GetDevProjectsProjectKeyRequestObject) (GetDevProjectsProjectKeyResponseObject, error) {
func (s server) GetDevProjectsProjectKey(ctx context.Context, request GetDevProjectsProjectKeyRequestObject) (GetDevProjectsProjectKeyResponseObject, error) {
store := model.StoreFromContext(ctx)
project, err := store.GetDevProject(ctx, request.ProjectKey)
if err != nil {
Expand Down Expand Up @@ -95,7 +97,7 @@ func (s Server) GetDevProjectsProjectKey(ctx context.Context, request GetDevProj
}, nil
}

func (s Server) PostDevProjectsProjectKey(ctx context.Context, request PostDevProjectsProjectKeyRequestObject) (PostDevProjectsProjectKeyResponseObject, error) {
func (s server) PostDevProjectsProjectKey(ctx context.Context, request PostDevProjectsProjectKeyRequestObject) (PostDevProjectsProjectKeyResponseObject, error) {
if request.Body.SourceEnvironmentKey == "" {
return PostDevProjectsProjectKey400JSONResponse{
ErrorResponseJSONResponse{
Expand Down Expand Up @@ -160,7 +162,7 @@ func (s Server) PostDevProjectsProjectKey(ctx context.Context, request PostDevPr
}, nil
}

func (s Server) PatchDevProjectsProjectKey(ctx context.Context, request PatchDevProjectsProjectKeyRequestObject) (PatchDevProjectsProjectKeyResponseObject, error) {
func (s server) PatchDevProjectsProjectKey(ctx context.Context, request PatchDevProjectsProjectKeyRequestObject) (PatchDevProjectsProjectKeyResponseObject, error) {
store := model.StoreFromContext(ctx)
project, err := model.UpdateProject(ctx, request.ProjectKey, request.Body.Context, request.Body.SourceEnvironmentKey)
if err != nil {
Expand Down Expand Up @@ -213,7 +215,7 @@ func (s Server) PatchDevProjectsProjectKey(ctx context.Context, request PatchDev
}, nil
}

func (s Server) PatchDevProjectsProjectKeySync(ctx context.Context, request PatchDevProjectsProjectKeySyncRequestObject) (PatchDevProjectsProjectKeySyncResponseObject, error) {
func (s server) PatchDevProjectsProjectKeySync(ctx context.Context, request PatchDevProjectsProjectKeySyncRequestObject) (PatchDevProjectsProjectKeySyncResponseObject, error) {
store := model.StoreFromContext(ctx)
project, err := model.UpdateProject(ctx, request.ProjectKey, nil, nil)
if err != nil {
Expand Down Expand Up @@ -266,7 +268,7 @@ func (s Server) PatchDevProjectsProjectKeySync(ctx context.Context, request Patc
}, nil
}

func (s Server) DeleteDevProjectsProjectKeyOverridesFlagKey(ctx context.Context, request DeleteDevProjectsProjectKeyOverridesFlagKeyRequestObject) (DeleteDevProjectsProjectKeyOverridesFlagKeyResponseObject, error) {
func (s server) DeleteDevProjectsProjectKeyOverridesFlagKey(ctx context.Context, request DeleteDevProjectsProjectKeyOverridesFlagKeyRequestObject) (DeleteDevProjectsProjectKeyOverridesFlagKeyResponseObject, error) {
store := model.StoreFromContext(ctx)
err := store.DeactivateOverride(ctx, request.ProjectKey, request.FlagKey)
if err != nil {
Expand All @@ -278,7 +280,7 @@ func (s Server) DeleteDevProjectsProjectKeyOverridesFlagKey(ctx context.Context,
return DeleteDevProjectsProjectKeyOverridesFlagKey204Response{}, nil
}

func (s Server) PutDevProjectsProjectKeyOverridesFlagKey(ctx context.Context, request PutDevProjectsProjectKeyOverridesFlagKeyRequestObject) (PutDevProjectsProjectKeyOverridesFlagKeyResponseObject, error) {
func (s server) PutDevProjectsProjectKeyOverridesFlagKey(ctx context.Context, request PutDevProjectsProjectKeyOverridesFlagKeyRequestObject) (PutDevProjectsProjectKeyOverridesFlagKeyResponseObject, error) {
if request.Body == nil {
return nil, errors.New("empty override body")
}
Expand All @@ -299,3 +301,29 @@ func (s Server) PutDevProjectsProjectKeyOverridesFlagKey(ctx context.Context, re
Value: override.Value,
}}, nil
}

func (s server) GetProjectsEnvironments(ctx context.Context, request GetProjectsEnvironmentsRequestObject) (GetProjectsEnvironmentsResponseObject, error) {
store := model.StoreFromContext(ctx)
project, err := store.GetDevProject(ctx, request.ProjectKey)
if err != nil {
return nil, err
}
if project == nil {
return GetProjectsEnvironments404JSONResponse{}, nil
}

environments, err := project.Environments(ctx)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to refactor this off the project rep still. On my list

if err != nil {
return nil, err
}

var envReps []Environment
for _, env := range environments {
envReps = append(envReps, Environment{
Key: env.Key,
Name: env.Name,
})
}

return GetProjectsEnvironments200JSONResponse(envReps), nil
}
4 changes: 2 additions & 2 deletions internal/dev_server/db/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ func (s Sqlite) UpdateProject(ctx context.Context, project model.Project) (bool,
}()
result, err := tx.ExecContext(ctx, `
UPDATE projects
SET flag_state = ?, last_sync_time = ?, context=?
SET flag_state = ?, last_sync_time = ?, context=?, source_environment_key=?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this intentionally left out? I saw some tests that might suggest so.

WHERE key = ?;
`, flagsStateJson, project.LastSyncTime, project.Context.JSONString(), project.Key)
`, flagsStateJson, project.LastSyncTime, project.Context.JSONString(), project.SourceEnvironmentKey, project.Key)
if err != nil {
return false, errors.Wrap(err, "unable to execute update project")
}
Expand Down
Loading
Loading