Compare commits

...

2 commits

3 changed files with 89 additions and 69 deletions

View file

@ -129,7 +129,7 @@ var pluginsInfoCmd = &cobra.Command{
# show information of a remote plugin # show information of a remote plugin
makeshift plugins info jinja2 smd makeshift plugins info jinja2 smd
# show information of a local plugin # show information of a local plugin (same as 'makeshift inspect')
makeshift plugins info --local $MAKESHIFT_ROOT/plugins/jinja2.so makeshift plugins info --local $MAKESHIFT_ROOT/plugins/jinja2.so
`, `,
Short: "Show plugin information", Short: "Show plugin information",

View file

@ -12,6 +12,7 @@ import (
"git.towk2.me/towk/makeshift/internal/format" "git.towk2.me/towk/makeshift/internal/format"
makeshift "git.towk2.me/towk/makeshift/pkg" makeshift "git.towk2.me/towk/makeshift/pkg"
"git.towk2.me/towk/makeshift/pkg/client" "git.towk2.me/towk/makeshift/pkg/client"
"git.towk2.me/towk/makeshift/pkg/service"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -32,9 +33,9 @@ var uploadCmd = &cobra.Command{
# upload an archive (extracted and saved on server) # upload an archive (extracted and saved on server)
makeshift upload -d @setup.tar.gz -t archive makeshift upload -d @setup.tar.gz -t archive
# upload a new profile with a specific path (used to set remote location) # upload multiple files with a specific path (used to set remote location)
makeshift upload profile -d @kubernetes.json -p nodes/kubernetes.json makeshift upload -d @kubernetes.json -p nodes/kubernetes.json
makeshift upload profile -d @slurm.json -d @compute.json -p nodes makeshift upload -d @slurm.json -d @compute.json -p nodes
`, `,
Short: "Upload files and directories", Short: "Upload files and directories",
PersistentPreRun: func(cmd *cobra.Command, args []string) { PersistentPreRun: func(cmd *cobra.Command, args []string) {
@ -79,15 +80,15 @@ var uploadCmd = &cobra.Command{
} }
var uploadProfilesCmd = &cobra.Command{ var uploadProfilesCmd = &cobra.Command{
Use: "profile [profileID]", Use: "profile [profile_id]",
Example: ` Example: `
# upload a new profile # upload a new profile
makeshift upload profile -d @compute.json makeshift upload profile -d @compute.json kubernetes.json
# upload a new profile with a specific path (used for lookup) # upload a new profile with a specific path
makeshift upload profile -d @kubernetes.json -n k8s makeshift upload profile -d @kubernetes.json
makeshift upload profile -d '{"id": "custom", "data": {}}' kubernetes.json
`, `,
Args: cobra.NoArgs,
Short: "Upload a new profile", Short: "Upload a new profile",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
var ( var (
@ -102,6 +103,28 @@ var uploadProfilesCmd = &cobra.Command{
err error err error
) )
// load files from args
for i, path := range args {
body, err = os.ReadFile(path)
if err != nil {
log.Error().Err(err).
Int("index", i).
Str("path", path).
Msg("failed to read profile file")
continue
}
var profile *makeshift.Profile
err = json.Unmarshal(body, &profile)
if err != nil {
log.Error().Err(err).
Int("index", i).
Str("path", path).
Msg("failed to unmarshal profile")
}
profiles = append(profiles, profile)
}
// send each loaded profile to server
for _, profile := range profiles { for _, profile := range profiles {
if profile == nil { if profile == nil {
continue continue
@ -113,42 +136,25 @@ var uploadProfilesCmd = &cobra.Command{
continue continue
} }
// send data to server
query = fmt.Sprintf("/profiles/%s", profile.ID) query = fmt.Sprintf("/profiles/%s", profile.ID)
res, body, err = c.MakeRequest(client.HTTPEnvelope{ res, body, err = c.MakeRequest(client.HTTPEnvelope{
Path: query, Path: query,
Method: http.MethodPost, Method: http.MethodPost,
Body: body, Body: body,
}) })
if err != nil { handleResponseError(res, host, query, err)
log.Error().Err(err).
Str("host", host).
Str("query", query).
Msg("failed to make request")
os.Exit(1)
}
if res.StatusCode != http.StatusOK {
log.Error().
Any("status", map[string]any{
"code": res.StatusCode,
"message": res.Status,
}).
Str("host", host).
Msg("response returned bad status")
os.Exit(1)
}
} }
}, },
} }
var uploadPluginsCmd = &cobra.Command{ var uploadPluginsCmd = &cobra.Command{
Use: "plugin", Use: "plugin [plugin_name]",
Example: ` Example: `
# upload a new plugin # upload a new plugin
makeshift upload plugin -d @slurm.so makeshift upload plugin -d @slurm.so
# upload a new plugin with a specific name (used for lookups) # upload a new plugin with a specific name (used for lookups)
makeshift upload plugin -d @cobbler.so -n merge makeshift upload plugin -d @cobbler.so
`, `,
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
Short: "Upload a new plugin", Short: "Upload a new plugin",
@ -156,14 +162,47 @@ var uploadPluginsCmd = &cobra.Command{
// make one request be host positional argument (restricted to 1 for now) // make one request be host positional argument (restricted to 1 for now)
// temp := append(handleArgs(args), processDataArgs(dataArgs)...) // temp := append(handleArgs(args), processDataArgs(dataArgs)...)
var ( var (
inputData []*makeshift.Profile host, _ = cmd.Flags().GetString("host")
dataArgs, _ = cmd.PersistentFlags().GetStringArray("data") dataArgs, _ = cmd.Flags().GetStringArray("data")
plugins = processFiles(dataArgs)
c = client.New(host)
res *http.Response
query string
body []byte
plugin makeshift.Plugin
err error
) )
temp := processProfiles(dataArgs)
for _, data := range temp { // load files from args
if data != nil { for i, path := range args {
inputData = append(inputData, data) body, err = os.ReadFile(path)
if err != nil {
log.Error().Err(err).
Int("index", i).
Str("path", path).
Msg("failed to read plugin file")
continue
} }
plugins[path] = body
}
for path, contents := range plugins {
plugin, err = service.LoadPluginFromFile(path)
if err != nil {
log.Error().Err(err).
Str("path", path).
Msg("failed to load plugin from file")
}
query = fmt.Sprintf("/plugins/%s", plugin.Name())
res, _, err = c.MakeRequest(client.HTTPEnvelope{
Path: query,
Method: http.MethodPost,
Body: contents,
})
handleResponseError(res, host, query, err)
} }
}, },
} }
@ -207,7 +246,7 @@ func processFiles(args []string) map[string][]byte {
// add loaded data to collection of all data // add loaded data to collection of all data
collection[path] = contents collection[path] = contents
} else { } else {
log.Warn().Msg("only files can be uploaded") log.Warn().Msg("only files can be uploaded (add @ before the path)")
continue continue
} }

View file

@ -88,33 +88,33 @@ func (s *Service) GetPluginRaw() http.HandlerFunc {
func (s *Service) CreatePlugin() http.HandlerFunc { func (s *Service) CreatePlugin() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
var ( var (
plugin makeshift.Plugin pluginName = chi.URLParam(r, "name")
path string body []byte
err error path string
err error
) )
plugin, err = getPluginFromRequestBody(r)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// helper to check for valid plugin name // helper to check for valid plugin name
var hasValidName = func(name string) bool { var hasValidName = func(name string) bool {
return name != "" && len(name) < 64 return name != "" && len(name) < 64
} }
// check for a valid plugin name // check for a valid plugin name
if !hasValidName(plugin.Name()) { if !hasValidName(pluginName) {
http.Error(w, "invalid name for plugin", http.StatusBadRequest)
return
}
body, err = io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
// save plugin at path using it's name path = s.PathForPluginWithName(pluginName)
path = s.PathForPluginWithName(plugin.Name()) err = os.WriteFile(path, body, 0o777)
err = SavePluginToFile(path, &plugin)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
@ -139,22 +139,3 @@ func (s *Service) DeletePlugin() http.HandlerFunc {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }
} }
func getPluginFromRequestBody(r *http.Request) (makeshift.Plugin, error) {
var (
plugin makeshift.Plugin
body []byte
err error
)
body, err = io.ReadAll(r.Body)
if err != nil {
return nil, err
}
err = json.Unmarshal(body, &plugin)
if err != nil {
return nil, err
}
return plugin, nil
}