func (cmd *Upload) request_file(filename string) (err error) { // アップロードするファイルへのReaderを作成 file, err := os.OpenFile(filename, os.O_RDONLY, 0600) if err != nil { return err } // アップロード先のURIを準備 uri, err := buildStorageUrl(cmd.config.EndPointUrl, cmd.destContainer, filename) if err != nil { return err } // PUTリクエストを作成 req, err := http.NewRequest("PUT", uri.String(), file) if err != nil { return err } contentType := cmd.detectContentType(filename) req.Header.Set("Content-type", contentType) req.Header.Set("X-Auth-Token", cmd.config.Token) // リクエストを実行 client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } switch { case resp.StatusCode == 404: return errors.New("Container was not found.") case resp.StatusCode >= 400: msg := fmt.Sprintf("Return %d status code from the server with message. [%s].", resp.StatusCode, extractErrorMessage(resp.Body), ) return errors.New(msg) } log := lib.GetLogInstance() log.Infof("%s (content-type: %s) was uploaded.", filename, contentType) return nil }
func (cmd *Download) DownloadObjects(srcpath string, destpath string) error { log := lib.GetLogInstance() // 対象の情報を取得 s := NewCommand("stat", cmd.config, cmd.stdStream, cmd.errStream).(*Stat) item, err := s.Stat(srcpath) if err != nil { return err } _, isContainer := item.(*Container) if isContainer { // オブジェクトの一覧を取得 l := NewCommand("list", cmd.config, cmd.stdStream, cmd.errStream).(*List) list, err := l.List(srcpath) if err != nil { return err } for i := 0; i < len(list); i++ { cmd.DownloadObjects(srcpath+"/"+list[i], destpath) } } else { log.Debugf("Downloading %s => %s", srcpath, destpath) u, err := buildStorageUrl(cmd.config.EndPointUrl, srcpath) if err != nil { return err } err = cmd.request(u, destpath) if err != nil { log.Infof("%s download error.", srcpath) return err } log.Infof("%s download complete.", srcpath) } return nil }
func (cmd *Upload) request_dir(dirname string) (err error) { // アップロード先のURIを準備 uri, err := buildStorageUrl(cmd.config.EndPointUrl, cmd.destContainer, dirname) if err != nil { return err } // PUTリクエストを作成 req, err := http.NewRequest("PUT", uri.String(), nil) if err != nil { return err } req.Header.Set("Content-type", "application/directory") req.Header.Set("X-Auth-Token", cmd.config.Token) // リクエストを実行 client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } switch { case resp.StatusCode == 404: return errors.New("Container was not found.") case resp.StatusCode >= 400: msg := fmt.Sprintf("Return %d status code from the server with message. [%s].", resp.StatusCode, extractErrorMessage(resp.Body), ) return errors.New(msg) } log := lib.GetLogInstance() log.Infof("%s directory was created.", dirname) return nil }
// 引数で渡された文字列を解決して、オブジェクトストレージのURIを返す func buildStorageUrl(endpointUrl string, paths ...string) (url *url.URL, err error) { log := lib.GetLogInstance() // オブジェクトストレージのURIを構築する rawurl := endpointUrl // EndPointUrl の末尾のスラッシュを削除 if strings.HasSuffix(rawurl, "/") { rawurl = rawurl[0 : len(rawurl)-1] } // パスを連結する先頭のスラッシュを補完 for i := 0; i < len(paths); i++ { paths[i] = strings.Trim(paths[i], "/") } rawurl += "/" + strings.Join(paths, "/") log.Debug(rawurl) return url.Parse(rawurl) }
// トークンの有効期限のチェックを行う // 有効期限内の場合は何もしない // 有効期限切れの場合は再取得を行う func (cmd *Auth) CheckTokenIsExpired(c *lib.Config) error { log := lib.GetLogInstance() // configでユーザ名などが空の場合は先に認証(authコマンド)を実行してくださいと返す if c.ApiUsername == "" || c.ApiPassword == "" || c.TenantId == "" { err := errors.New("ApiUsername, Apipassword and TenantID was not found in a config file. You should execute an auth command. (See \"conoha-ojs auth\").") return err } // 以下をすべて満たす場合はキャッシュ済みのトークンを使うため、処理をスキップする // * トークンが取得済みである(空文字でない) // * エンドポイントURLが取得できている(空文字でない) // * トークンの有効期限内である doUpdate := false if c.Token == "" || c.EndPointUrl == "" { doUpdate = true } now := time.Now().UTC() te, err := time.Parse(time.RFC1123, c.TokenExpires) if err != nil || now.After(te) { doUpdate = true } if !doUpdate { log.Debug("Using the cached token.") return nil } // 認証URLの指定がない場合はデフォルトを使用 if cmd.authUrl == "" { cmd.authUrl = DEFAULT_AUTH_URL } return cmd.request(c, c.ApiUsername, c.ApiPassword, c.TenantId) }
func (cmd *Delete) Delete(path string) error { log := lib.GetLogInstance() // 対象の情報を取得 s := NewCommand("stat", cmd.config, cmd.stdStream, cmd.errStream).(*Stat) item, err := s.Stat(path) if err != nil { return err } _, isContainer := item.(*Container) if isContainer { // 配下のオブジェクト一覧を取得 l := NewCommand("list", cmd.config, cmd.stdStream, cmd.errStream).(*List) list, err := l.List(path) if err != nil { return err } for i := 0; i < len(list); i++ { cmd.Delete(path + "/" + list[i]) } } u, err := buildStorageUrl(cmd.config.EndPointUrl, path) if err != nil { return err } err = cmd.request(u) if err != nil { return err } log.Infof("%s was deleted.", path) return nil }
// 引数のhttp.Requestに、メタデータ、ReadACL, WriteACLのヘッダ情報を追加する func (cmd *Post) addHeaders(req *http.Request, item Item) { log := lib.GetLogInstance() _, isContainer := item.(*Container) // メタデータをセット for name, value := range cmd.metadatas { var header = "X-" // valueが空の場合はメタデータの削除 if value == "" { header += "Remove-" } // コンテナの場合とオブジェクトの場合でヘッダ名が違う if isContainer { header += "Container-Meta-" } else { header += "Object-Meta-" } header += name req.Header.Add(header, value) log.Debugf("Set meta data: %s=%s", header, value) } // Read-ACLとWrite-ACL if isContainer && cmd.readAcl != "_no_assign_" { req.Header.Add("X-Container-Read", cmd.readAcl) log.Debugf("Set Read ACL: %s", cmd.readAcl) } if isContainer && cmd.writeAcl != "_no_assign_" { req.Header.Add("X-Container-Write", cmd.writeAcl) log.Debugf("Set Write ACL: %s", cmd.readAcl) } }
func run() (exitCode int, err error) { // log log := lib.GetLogInstance() // 実行するコマンド var cmd command.Commander // 出力先 stdStream := os.Stdout errStream := os.Stderr // 設定を読み込む config := lib.NewConfig() // コマンドを実行 if len(os.Args) <= 1 { // コマンドが未指定の場合は使用法を表示 cmd = command.NewCommand("nocommand", config, stdStream, errStream) return cmd.Run() } command_name := os.Args[1] log.Debugf("Command: \"%v\"", command_name) if command_name == "auth" { // 認証情報を更新(コマンドライン引数から認証情報を設定する) auth := command.NewCommand("auth", config, stdStream, errStream) exitCode, err = auth.Run() if err != nil { return exitCode, err } } else if command_name == "deauth" { // 認証情報を削除 deauth := command.NewCommand("deauth", config, stdStream, errStream) exitCode, err = deauth.Run() if err != nil { return exitCode, err } } else if command_name == "version" { // バージョン表示 v := command.NewCommand("version", config, stdStream, errStream) exitCode, err = v.Run() if err != nil { return exitCode, err } } else { // 認証情報を更新 auth := command.NewCommand("auth", config, stdStream, errStream).(*command.Auth) if err = auth.CheckTokenIsExpired(config); err != nil { return 1, err } // コマンドを実行 cmd := command.NewCommand(command_name, config, stdStream, errStream) code, err := cmd.Run() if err != nil { return code, err } } return command.ExitCodeOK, nil }