diff --git a/pkg/models.go b/pkg/models.go new file mode 100644 index 0000000..53a0103 --- /dev/null +++ b/pkg/models.go @@ -0,0 +1,33 @@ +package makeshift + +import "git.towk2.me/towk/makeshift/pkg/storage" + +type Profile struct { + ID string `json:"id"` // profile ID + Description string `json:"description,omitempty"` // profile description + Tags []string `json:"tags,omitempty"` // tags used for ... + Paths []string `json:"paths,omitempty"` // paths to download + Plugins []string `json:"plugins,omitempty"` // plugins to run + Data map[string]any `json:"data,omitempty"` // include render data +} + +type Plugin interface { + Name() string + Version() string + Description() string + Metadata() Metadata + + Init() error + Run(data storage.KVStore, args []string) error + Cleanup() error +} +type Metadata map[string]any +type Hook struct { + Data storage.KVStore + Args []string + Plugin Plugin +} + +func (h *Hook) Run() error { + return h.Plugin.Run(h.Data, h.Args) +} diff --git a/pkg/plugin.go b/pkg/plugin.go deleted file mode 100644 index b3841a7..0000000 --- a/pkg/plugin.go +++ /dev/null @@ -1,16 +0,0 @@ -package configurator - -import ( - "git.towk2.me/towk/configurator/pkg/storage" -) - -type Plugin interface { - Name() string - Version() string - Description() string - Metadata() map[string]string - - Init() error - Run(data storage.KVStore, args []string) error - Cleanup() error -} diff --git a/pkg/service/profile.go b/pkg/service/profile.go deleted file mode 100644 index 9ba7f2e..0000000 --- a/pkg/service/profile.go +++ /dev/null @@ -1,290 +0,0 @@ -package service - -import ( - "encoding/json" - "fmt" - "io" - "io/fs" - "net/http" - "os" - "path/filepath" - - "github.com/go-chi/chi/v5" - "github.com/tidwall/sjson" -) - -type Profile struct { - ID string `json:"id"` // profile ID - Description string `json:"description"` // profile description - Tags []string `json:"tags"` // tags used for ... - Paths []string `json:"paths"` // paths to download - Plugins []string `json:"plugins"` // plugins to run - Data map[string]any `json:"data"` // include render data -} - -func (s *Service) GetProfiles() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var ( - path = s.RootPath + RELPATH_PROFILES - profiles []*Profile - contents []byte - err error - ) - - // walk profiles directory to load all profiles - err = filepath.Walk(path, func(path string, info fs.FileInfo, err error) error { - if err != nil { - return err - } - - // skip directories - if info.IsDir() { - return nil - } - - // read file contents - var profile *Profile - profile, err = LoadProfileFromFile(path) - if err != nil { - return err - } - - profiles = append(profiles, profile) - - fmt.Println(path, info.Size()) - return nil - }) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - - // marshal and send all the profiles - contents, err = json.Marshal(profiles) - if err != nil { - http.Error(w, fmt.Sprintf("failed to marshal profiles: %v", err), http.StatusInternalServerError) - } - - _, err = w.Write(contents) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - } -} - -// func (s *Service) CreateProfiles() http.HandlerFunc { -// return func(w http.ResponseWriter, r *http.Request) { -// var ( -// path = chi.URLParam(r, "path") -// err error -// ) - -// } -// } - -func (s *Service) GetProfile() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var ( - id = chi.URLParam(r, "id") - path = s.PathForProfileWithID(id) - contents []byte - err error - ) - - contents, err = loadProfileContents(path) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - - _, err = w.Write(contents) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - } -} - -func (s *Service) CreateProfile() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - type input struct { - Path string `json:"path"` - Profile *Profile `json:"profile"` - } - var ( - body, contents []byte - in input - err error - ) - - body, err = io.ReadAll(r.Body) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // use the request info to build profile - err = json.Unmarshal(body, &in) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - // serialize just the profile part - contents, err = json.Marshal(in.Profile) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - // create a new profile on disk - err = os.WriteFile(in.Path, contents, os.ModePerm) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - w.WriteHeader(http.StatusOK) - } -} - -func (s *Service) SetProfileData() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var ( - body, contents []byte - newContents string - profile *Profile - path string - err error - ) - - body, err = io.ReadAll(r.Body) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - err = json.Unmarshal(body, &profile) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - // make sure the request data sets an ID - if profile.ID == "" { - http.Error(w, "ID must be set to a non-empty value", http.StatusBadRequest) - return - } - - // read the contents the file with profile ID - path = s.PathForProfileWithID(profile.ID) - contents, err = os.ReadFile(path) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // modify the data of the profile's contents - newContents, err = sjson.Set(string(contents), "data", profile.Data) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // write only the data to the file with ID - err = os.WriteFile(path, []byte(newContents), os.ModePerm) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - } -} - -func (s *Service) DeleteProfileData() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var ( - id = chi.URLParam(r, "id") - path = s.PathForProfileWithID(id) - profile *Profile - err error - ) - - // get the profile - profile, err = LoadProfileFromFile(path) - if err != nil { - http.Error(w, err.Error(), http.StatusBadGateway) - return - } - - // delete the profile data - profile.Data = map[string]any{} - - // save the profile back to the file to update - SaveProfileToFile(path, profile) - - } -} - -func (s *Service) GetProfileData() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var ( - id = chi.URLParam(r, "id") - path = s.PathForProfileWithID(id) - profile *Profile - body []byte - err error - ) - - profile, err = LoadProfileFromFile(path) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - // only marshal the profile data and not entire profile - body, err = json.Marshal(profile.Data) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // write body to response - _, err = w.Write(body) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - } -} - -// func (s *Service) CreateProfilePath() http.HandlerFunc { -// return func(w http.ResponseWriter, r *http.Request) { - -// w.WriteHeader(http.StatusOK) -// } -// } - -// func (s *Service) DeleteProfilePath() http.HandlerFunc { -// return func(w http.ResponseWriter, r *http.Request) {} -// } - -// func (s *Service) GetProfilePath() http.HandlerFunc { -// return func(w http.ResponseWriter, r *http.Request) {} -// } - -func loadProfileContents(path string) ([]byte, error) { - var ( - contents []byte - profile *Profile - err error - ) - profile, err = LoadProfileFromFile(path) - if err != nil { - return nil, fmt.Errorf("failed to load profile from file: %v", err) - } - - contents, err = json.Marshal(profile) - if err != nil { - return nil, fmt.Errorf("failed to marshal profile: %v", err) - } - return contents, nil -}