init from gitlab

This commit is contained in:
texm
2023-04-25 14:33:14 +08:00
parent 6a85a41ff0
commit c8202a5c82
281 changed files with 19861 additions and 1 deletions

325
internal/server/dto/apps.go Normal file
View File

@@ -0,0 +1,325 @@
package dto
import (
"github.com/texm/dokku-go"
"time"
)
type GetAppOverviewRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppOverviewResponse struct {
Name string `json:"name,omitempty"`
IsSetup bool `json:"is_setup"`
SetupMethod string `json:"setup_method"`
GitDeployBranch string `json:"git_deploy_branch"`
GitLastUpdated string `json:"git_last_updated"`
IsDeployed bool `json:"is_deployed"`
IsRunning bool `json:"is_running"`
NumProcesses int `json:"num_processes"`
CanScale bool `json:"can_scale"`
Restore bool `json:"restore"`
}
type GetAllAppsOverviewResponse struct {
Apps []GetAppOverviewResponse `json:"apps"`
}
type GetAppsListItem struct {
Name string `json:"name"`
Type string `json:"type"`
}
type GetAppsListResponse struct {
Apps []GetAppsListItem `json:"apps"`
}
type GetAppInfoRequest struct {
Name string `query:"name" validate:"appName"`
}
type DestroyAppRequest struct {
Name string `json:"name"`
}
type AppInfo struct {
Name string `json:"name"`
Directory string `json:"directory"`
DeploySource string `json:"deploy_source"`
DeploySourceMetadata string `json:"deploy_source_metadata"`
CreatedAt time.Time `json:"created_at"`
IsLocked bool `json:"is_locked"`
}
type GetAppInfoResponse struct {
Info AppInfo `json:"info"`
}
type ManageAppRequest struct {
Name string `json:"name" validate:"appName"`
}
type GetAppSetupStatusRequest struct {
Name string `json:"name" validate:"appName"`
}
type GetAppSetupStatusResponse struct {
IsSetup bool `json:"is_setup"`
Method string `json:"method"`
}
type GetAppSetupConfigRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppSetupConfigResponse struct {
IsSetup bool `json:"is_setup"`
Method string `json:"method"`
DeploymentBranch string `json:"deployment_branch,omitempty"`
RepoURL string `json:"repo_url,omitempty"`
RepoGitRef string `json:"repo_git_ref,omitempty"`
Image string `json:"image,omitempty"`
}
type SetupAppNewRepoRequest struct {
Name string `json:"name" validate:"appName"`
DeploymentBranch string `json:"deployment_branch"`
}
type SetupAppSyncRepoRequest struct {
Name string `json:"name" validate:"appName"`
RepositoryURL string `json:"repository_url"`
GitRef string `json:"git_ref"`
}
type SetupAppPullImageRequest struct {
Name string `json:"name" validate:"appName"`
Image string `json:"image"`
}
type SetupAppUploadArchiveRequest struct {
Name string `form:"name" validate:"appName"`
}
type RenameAppRequest struct {
CurrentName string `json:"current_name" validate:"appName"`
NewName string `json:"new_name" validate:"appName"`
}
/*
methods = ["Git Push", "Git Repository", "Archive File", "Dockerfile", "Docker Image"]
options = [["deploymentBranch", "envVar"], ["repositoryURL", "gitRef"], ["file"],
["dockerfilePath", "usingBuildkit"], ["image"]]
*/
type DeployAppRequest struct {
Name string `json:"name" validate:"appName"`
Method string `json:"method" validate:"alpha"`
Options map[string]string `json:"options" validate:"alpha"`
}
type GetAppServicesRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppDeployChecksRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppDeployChecksResponse struct {
AllDisabled bool `json:"all_disabled"`
AllSkipped bool `json:"all_skipped"`
DisabledProcesses []string `json:"disabled_processes"`
SkippedProcesses []string `json:"skipped_processes"`
}
type SetAppDeployChecksRequest struct {
Name string `json:"name" validate:"appName"`
// enabled, disabled, skipped
State string `json:"state" validate:"alpha"`
}
type SetAppProcessDeployChecksRequest struct {
Name string `json:"name" validate:"appName"`
Process string `json:"process" validate:"processName"`
// enabled, disabled, skipped
State string `json:"state" validate:"alpha"`
}
type GetAppProcessesRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppProcessesResponse struct {
Processes []string `json:"processes"`
}
type GetAppProcessReportRequest struct {
Name string `query:"name" validate:"appName"`
}
type AppProcessInfo struct {
Scale int `json:"scale"`
Resources dokku.ResourceSettings `json:"resources"`
}
type GetAppProcessReportResponse struct {
ResourceDefaults dokku.ResourceSettings `json:"resource_defaults"`
Processes map[string]AppProcessInfo `json:"processes"`
}
type AppResources struct {
CPU *int `json:"cpu"`
Memory *int `json:"memory"`
MemoryUnit *string `json:"memory_unit"`
}
type SetAppProcessResourcesRequest struct {
Name string `json:"name" validate:"appName"`
Process string `json:"process" validate:"processName"`
ResourceLimits AppResources `json:"limits"`
ResourceReservations AppResources `json:"reservations"`
}
type GetAppProcessScaleRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppProcessScaleResponse struct {
ProcessScale map[string]int `json:"process_scale"`
}
type SetAppProcessScaleRequest struct {
Name string `json:"name" validate:"appName"`
Process string `json:"process" validate:"processName"`
Scale int `json:"scale" validate:"numeric"`
SkipDeploy bool `json:"skip_deploy"`
}
type GetAppDomainsReportRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppDomainsReportResponse struct {
Domains []string `json:"domains"`
Enabled bool `json:"enabled"`
}
type SetAppDomainsEnabledRequest struct {
Name string `json:"name" validate:"appName"`
Enabled bool `json:"enabled"`
}
type GetAppLetsEncryptEnabledRequest struct {
Name string `query:"name" validate:"appName"`
}
type SetAppLetsEncryptEnabledRequest struct {
Name string `json:"name" validate:"appName"`
Enabled bool `json:"enabled"`
}
type GetAppDomainsRequest struct {
Name string `query:"name" validate:"appName"`
}
type AlterAppDomainRequest struct {
Name string `json:"name" validate:"appName"`
Domain string `json:"domain" validate:"hostname_rfc1123"`
}
type AlterNetworkRequest struct {
Network string `query:"network"`
}
type ListNetworksResponse struct {
Networks []string `json:"networks"`
}
type GetAppNetworksReportRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppNetworksReportResponse struct {
AttachInitial string `json:"attach_initial"`
AttachPostCreate string `json:"attach_post_create"`
AttachPostDeploy string `json:"attach_post_deploy"`
BindAllInterfaces bool `json:"bind_all_interfaces"`
TLD string `json:"tld"`
WebListeners string `json:"web_listeners"`
}
type SetAppNetworksRequest struct {
Name string `query:"name" validate:"appName"`
Initial *string `json:"attach_initial"`
PostCreate *string `json:"attach_post_create"`
PostDeploy *string `json:"attach_post_deploy"`
BindAllInterfaces *bool `json:"bind_all_interfaces"`
TLD *string `json:"tld"`
}
type GetAppLogsRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppLogsResponse struct {
Logs []string `json:"logs"`
}
type GetAppConfigRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppConfigResponse struct {
Config map[string]string `json:"config"`
}
type SetAppConfigRequest struct {
Name string `json:"name" validate:"appName"`
// validate keys and values are alphanumeric
Config map[string]string `json:"config" validate:"dive,keys,alphanum,endkeys,alphanum"`
// Config map[string]string `json:"config"`
}
type GetAppStorageRequest struct {
Name string `query:"name" validate:"appName"`
}
type StorageMount struct {
HostDir string `json:"hostDir"`
ContainerDir string `json:"mountDir"`
IsBuildMount bool `json:"isBuildMount"`
IsRunMount bool `json:"isRunMount"`
IsDeployMount bool `json:"isDeployMount"`
}
type GetAppStorageResponse struct {
Mounts []StorageMount `json:"mounts"`
}
type AlterAppStorageRequest struct {
Name string `json:"name" validate:"appName"`
RestartApp bool `json:"restart"`
// TODO: validation for these
StorageType string `json:"selectedType"`
HostDir string `json:"hostDir" validate:"gte=2,alphanum"`
ContainerDir string `json:"mountDir"`
}
type GetAppBuilderRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppBuilderResponse struct {
Selected string `json:"selected"`
}
type SetAppBuilderRequest struct {
Name string `json:"name" validate:"appName"`
Builder string `json:"builder" validate:"alphanum"`
}
type GetAppBuildDirectoryRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetAppBuildDirectoryResponse struct {
Directory string `json:"directory"`
}
type SetAppBuildDirectoryRequest struct {
Name string `json:"name" validate:"appName"`
Directory string `json:"directory" validate:"alphanum"`
}
type ClearAppBuildDirectoryRequest struct {
Name string `query:"name" validate:"appName"`
}

View File

@@ -0,0 +1,65 @@
package dto
type PasswordLoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
TotpCode string `json:"totp"`
}
type PasswordLoginResponse struct {
Success bool `json:"success"`
NeedsTotp bool `json:"needs_totp"`
}
type GithubAuthRequest struct {
Code string `json:"code"`
RedirectURL string `json:"redirect_url"`
}
type GetGithubSetupStatus struct {
AppCreated bool `json:"created"`
}
type CreateGithubAppRequest struct {
Code string `json:"code"`
}
type CreateGithubAppResponse struct {
Slug string `json:"slug"`
}
type InstallGithubAppResponse struct {
InstallURL string `json:"install_url"`
}
type CompleteGithubSetupRequest struct {
Code string `json:"code"`
InstallationId int64 `json:"installation_id"`
}
type GetGithubAuthInfoResponse struct {
ClientID string `json:"client_id"`
}
type GenerateTotpResponse struct {
Secret string `json:"secret"`
Image string `json:"image"`
RecoveryCode string `json:"recovery_code"`
}
type ConfirmTotpRequest struct {
Secret string `json:"secret"`
Code string `json:"code"`
}
type ConfirmTotpResponse struct {
Valid bool `json:"valid"`
}
type CompletePasswordSetupRequest struct {
Username string `json:"username"`
Password string `json:"password"`
Enable2FA bool `json:"enable_2fa"`
TotpSecret string `json:"totp_secret"`
RecoveryCode string `json:"recovery_code"`
}

View File

@@ -0,0 +1,38 @@
package dto
import (
"time"
)
type GetCommandExecutionStatusRequest struct {
ExecutionID string `query:"execution_id" validate:"required"`
}
type CommandExecutionResponse struct {
ExecutionID string `json:"execution_id"`
}
type OutputLine struct {
Msg string `json:"message"`
Type string `json:"type"`
PolledAt time.Time `json:"polled_at"`
}
type CommandExecutionStatusResponse struct {
Started bool `json:"started"`
Finished bool `json:"finished"`
Success bool `json:"success"`
CombinedOutput []OutputLine `json:"output"`
}
type AppExecInProcessRequest struct {
AppName string `json:"appName" validate:"appName"`
ProcessName string `json:"processName" validate:"required"`
Command string `json:"command"`
}
type AppExecInProcessResponse struct {
Output string `json:"output"`
Error string `json:"error"`
}

117
internal/server/dto/dto.go Normal file
View File

@@ -0,0 +1,117 @@
package dto
import (
"errors"
"fmt"
"github.com/go-playground/validator/v10"
"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"github.com/texm/dokku-go"
"net/http"
"reflect"
"regexp"
)
// allow alphanumeric, underscores, and hyphens
func appNameCharsValidator() func(level validator.FieldLevel) bool {
r, err := regexp.Compile("\\w[\\w\\-]*")
if err != nil {
log.Fatal().Err(err).Msg("failed to compile regexp")
}
return func(fl validator.FieldLevel) bool {
if fl.Field().Kind() != reflect.String {
return false
}
str := fl.Field().String()
return r.FindString(str) == str
}
}
type requestValidator struct {
validator *validator.Validate
}
func (rv *requestValidator) Validate(i interface{}) error {
return rv.validator.Struct(i)
}
func NewRequestValidator() *requestValidator {
v := validator.New()
err := v.RegisterValidation("appNameChars", appNameCharsValidator())
if err != nil {
log.Fatal().Err(err).Msg("failed to register validator")
}
v.RegisterAlias("appName", "appNameChars,min=4,max=16")
v.RegisterAlias("processName", "appNameChars,min=2,max=16")
return &requestValidator{validator: v}
}
type RequestError struct {
err error
isBinding bool
isInvalidFormat bool
isInvalidData bool
validationErrors []validator.FieldError
}
func (r *RequestError) String() string {
return fmt.Sprintf("%+v", r.validationErrors)
}
func (r *RequestError) ToHTTP() *echo.HTTPError {
err := echo.NewHTTPError(http.StatusBadRequest).SetInternal(r.err)
if r.isBinding {
err.Message = echo.Map{"type": "binding"}
} else if r.isInvalidFormat {
err.Message = echo.Map{"type": "format"}
} else if r.isInvalidData {
fields := map[string]string{}
for _, fe := range r.validationErrors {
fields[fe.Field()] = fe.ActualTag()
}
err.Message = echo.Map{
"type": "validation",
"fields": fields,
}
} else {
err = echo.ErrInternalServerError
}
return err
}
func BindRequest(c echo.Context, r any) *RequestError {
if err := c.Bind(r); err != nil {
return &RequestError{
err: err,
isBinding: true,
}
}
if err := c.Validate(r); err != nil {
if errors, ok := err.(validator.ValidationErrors); ok {
return &RequestError{
err: err,
isInvalidData: true,
validationErrors: errors,
}
}
return &RequestError{
err: err,
isInvalidFormat: true,
}
}
return nil
}
func MaybeConvertDokkuError(err error) *echo.HTTPError {
if errors.Is(err, dokku.InvalidAppError) {
return echo.NewHTTPError(http.StatusBadRequest, "no such app")
}
if errors.Is(err, dokku.NameTakenError) {
return echo.NewHTTPError(http.StatusBadRequest, "duplicate app name")
}
return nil
}

View File

@@ -0,0 +1,114 @@
package dto
type ManageServiceRequest struct {
Name string `json:"name" validate:"appName"`
Type string `json:"type" validate:"alphanum"`
}
type GenericServiceRequest struct {
Name string `query:"name" validate:"appName"`
Type string `query:"type" validate:"alphanum"`
}
type GenericServiceCreationConfig struct {
ConfigOptions *string `json:"config-options"`
// validate inner pairs are len=2
CustomEnv *[][]string `json:"custom-env"`
Image *string `json:"image"`
ImageVersion *string `json:"image-version"`
MemoryLimit *string `json:"memory"`
Password *string `json:"password"`
RootPassword *string `json:"root-password"`
SharedMemorySize *string `json:"shm-size"`
}
type CreateGenericServiceRequest struct {
Name string `json:"name" validate:"appName"`
ServiceType string `json:"type"`
Config GenericServiceCreationConfig `json:"config"`
}
type CloneServiceRequest struct {
Name string `json:"name" validate:"appName"`
NewName string `json:"newName" validate:"appName"`
}
type ServiceInfo struct {
Name string `json:"name"`
Type string `json:"type"`
}
type ListServicesResponse struct {
Services []ServiceInfo `json:"services"`
}
type GetServiceInfoResponse struct {
Info map[string]string `json:"info"`
}
type GetServiceTypeRequest struct {
Name string `query:"name" validate:"appName"`
}
type GetServiceTypeResponse struct {
Type string `json:"type"`
}
type LinkGenericServiceToAppRequest struct {
ServiceName string `json:"service_name" validate:"appName"`
AppName string `json:"app_name" validate:"appName"`
Alias string `json:"alias"`
QueryString string `json:"query_string"`
}
type GetServiceLinkedAppsResponse struct {
Apps []string `json:"apps"`
}
type GetServiceLogsResponse struct {
Logs []string `json:"logs"`
}
type GetServiceBackupReportRequest struct {
Name string `query:"name" validate:"appName"`
}
type ServiceBackupReport struct {
AuthSet bool `json:"auth_set"`
EncryptionSet bool `json:"encryption_set"`
Bucket string `json:"bucket"`
Schedule string `json:"schedule"`
}
type GetServiceBackupReportResponse struct {
Report ServiceBackupReport `json:"report"`
}
type RunServiceBackupRequest struct {
Name string `query:"name" validate:"appName"`
}
type BackupsAuthConfig struct {
AccessKeyId string `json:"access_key_id"`
SecretKey string `json:"secret_key"`
Region string `json:"region"`
SignatureVersion string `json:"signature_version"`
EndpointUrl string `json:"endpoint_url"`
}
type SetServiceBackupsAuthRequest struct {
Name string `json:"name" validate:"appName"`
Config BackupsAuthConfig `json:"config"`
}
type SetServiceBackupsBucketRequest struct {
Name string `json:"name" validate:"appName"`
Bucket string `json:"bucket"`
}
type SetServiceBackupsScheduleRequest struct {
Name string `json:"name" validate:"appName"`
Schedule string `json:"schedule"`
}
type SetServiceBackupsEncryptionRequest struct {
Name string `json:"name" validate:"appName"`
Passphrase string `json:"passphrase"`
}

View File

@@ -0,0 +1,78 @@
package dto
import "github.com/texm/dokku-go"
type GetVersionsResponse struct {
Dokku string `json:"dokku"`
Shokku string `json:"shokku"`
}
type GetLetsEncryptStatusResponse struct {
Installed bool `json:"installed"`
Email string `json:"email"`
}
type User struct {
Name string `json:"name"`
Source string `json:"source"`
SSHKeys []string `json:"ssh_keys"`
}
type GetUsersResponse struct {
Users []User `json:"users"`
}
type GetSSHKeysResponse struct {
Keys []dokku.SSHKey `json:"keys"`
}
type GetGlobalDomainsResponse struct {
Domains []string `json:"domains"`
Enabled bool `json:"enabled"`
}
type AlterGlobalDomainRequest struct {
Domain string `json:"domain"`
}
type DeleteGlobalDomainRequest struct {
Domain string `query:"domain"`
}
type AddGitAuthRequest struct {
Host string `json:"host"`
Username string `json:"username"`
Password string `json:"password"`
}
type RemoveGitAuthRequest struct {
Host string `json:"host"`
}
type SetDockerRegistryRequest struct {
Server string `json:"server"`
Username string `json:"username"`
Password string `json:"password"`
}
type GetDockerRegistryReportResponse struct {
Server string `json:"server"`
PushOnRelease bool `json:"push_on_release"`
}
type SetEventLoggingEnabledRequest struct {
Enabled bool `json:"enabled"`
}
type GetEventLogsListResponse struct {
Events []string `json:"events"`
}
type GetEventLogsResponse struct {
Logs string `json:"logs"`
}
type PluginInfo struct {
Name string `json:"name"`
Version string `json:"version"`
Enabled bool `json:"enabled"`
Description string `json:"description"`
}
type ListPluginsResponse struct {
Plugins []PluginInfo `json:"plugins"`
}

View File

@@ -0,0 +1,6 @@
package dto
type GetSetupStatusResponse struct {
IsSetup bool `json:"is_setup"`
Method string `json:"method"`
}