github.com/oam-dev/kubevela@v1.9.11/pkg/utils/parse.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package utils
    18  
    19  import (
    20  	"fmt"
    21  	"net/url"
    22  	"strings"
    23  
    24  	"github.com/pkg/errors"
    25  )
    26  
    27  // TypeLocal represents github
    28  const TypeLocal = "local"
    29  
    30  // TypeOss represent oss
    31  const TypeOss = "oss"
    32  
    33  // TypeGithub represents github
    34  const TypeGithub = "github"
    35  
    36  // TypeGitee represents gitee
    37  const TypeGitee = "gitee"
    38  
    39  // TypeGitlab represents gitlab
    40  const TypeGitlab = "gitlab"
    41  
    42  // TypeUnknown represents parse failed
    43  const TypeUnknown = "unknown"
    44  
    45  // errInvalidFormatMsg with the message to be returned in case of a format error.
    46  const errInvalidFormatMsg = "invalid format "
    47  
    48  // Content contains different type of content needed when building Registry
    49  type Content struct {
    50  	OssContent
    51  	GithubContent
    52  	GiteeContent
    53  	GitlabContent
    54  	LocalContent
    55  }
    56  
    57  // LocalContent for local registry
    58  type LocalContent struct {
    59  	AbsDir string `json:"abs_dir"`
    60  }
    61  
    62  // OssContent for oss registry
    63  type OssContent struct {
    64  	EndPoint string `json:"bucket_url"`
    65  	Bucket   string `json:"bucket"`
    66  }
    67  
    68  // GithubContent for cap center
    69  type GithubContent struct {
    70  	Owner string `json:"owner"`
    71  	Repo  string `json:"repo"`
    72  	Path  string `json:"path"`
    73  	Ref   string `json:"ref"`
    74  }
    75  
    76  // GiteeContent for cap center
    77  type GiteeContent struct {
    78  	Owner string `json:"gitee_owner"`
    79  	Repo  string `json:"gitee_repo"`
    80  	Path  string `json:"gitee_path"`
    81  	Ref   string `json:"gitee_ref"`
    82  }
    83  
    84  // GitlabContent for cap center
    85  type GitlabContent struct {
    86  	Host  string `json:"gitlab_host"`
    87  	Owner string `json:"gitlab_owner"`
    88  	Repo  string `json:"gitlab_repo"`
    89  	Path  string `json:"gitlab_path"`
    90  	Ref   string `json:"gitlab_ref"`
    91  	PId   int    `json:"gitlab_pid"`
    92  }
    93  
    94  // Parse will parse config from address
    95  func Parse(addr string) (string, *Content, error) {
    96  	URL, err := url.Parse(addr)
    97  	if err != nil {
    98  		return "", nil, err
    99  	}
   100  	l := strings.Split(strings.TrimPrefix(URL.Path, "/"), "/")
   101  	switch URL.Scheme {
   102  	case "http", "https":
   103  		switch URL.Host {
   104  		case "github.com":
   105  			// We support two valid format:
   106  			// 1. https://github.com/<owner>/<repo>/tree/<branch>/<path-to-dir>
   107  			// 2. https://github.com/<owner>/<repo>/<path-to-dir>
   108  			if len(l) < 3 {
   109  				return "", nil, errors.New(errInvalidFormatMsg + addr)
   110  			}
   111  			if l[2] == "tree" {
   112  				// https://github.com/<owner>/<repo>/tree/<branch>/<path-to-dir>
   113  				if len(l) < 5 {
   114  					return "", nil, errors.New(errInvalidFormatMsg + addr)
   115  				}
   116  				return TypeGithub, &Content{
   117  					GithubContent: GithubContent{
   118  						Owner: l[0],
   119  						Repo:  l[1],
   120  						Path:  strings.Join(l[4:], "/"),
   121  						Ref:   l[3],
   122  					},
   123  				}, nil
   124  			}
   125  			// https://github.com/<owner>/<repo>/<path-to-dir>
   126  			return TypeGithub, &Content{
   127  					GithubContent: GithubContent{
   128  						Owner: l[0],
   129  						Repo:  l[1],
   130  						Path:  strings.Join(l[2:], "/"),
   131  						Ref:   "", // use default branch
   132  					},
   133  				},
   134  				nil
   135  		case "api.github.com":
   136  			if len(l) != 5 {
   137  				return "", nil, errors.New(errInvalidFormatMsg + addr)
   138  			}
   139  			//https://api.github.com/repos/<owner>/<repo>/contents/<path-to-dir>
   140  			return TypeGithub, &Content{
   141  					GithubContent: GithubContent{
   142  						Owner: l[1],
   143  						Repo:  l[2],
   144  						Path:  l[4],
   145  						Ref:   URL.Query().Get("ref"),
   146  					},
   147  				},
   148  				nil
   149  		case "gitee.com":
   150  			// We support two valid format:
   151  			// 1. https://gitee.com/<owner>/<repo>/tree/<branch>/<path-to-dir>
   152  			// 2. https://gitee.com/<owner>/<repo>/<path-to-dir>
   153  			if len(l) < 3 {
   154  				return "", nil, errors.New(errInvalidFormatMsg + addr)
   155  			}
   156  			switch l[2] {
   157  			case "tree":
   158  				// https://gitee.com/<owner>/<repo>/tree/<branch>/<path-to-dir>
   159  				if len(l) < 5 {
   160  					return "", nil, errors.New(errInvalidFormatMsg + addr)
   161  				}
   162  				return TypeGitee, &Content{
   163  					GiteeContent: GiteeContent{
   164  						Owner: l[0],
   165  						Repo:  l[1],
   166  						Path:  strings.Join(l[4:], "/"),
   167  						Ref:   l[3],
   168  					},
   169  				}, nil
   170  			default:
   171  				// https://gitee.com/<owner>/<repo>/<path-to-dir>
   172  				return TypeGitee, &Content{
   173  					GiteeContent: GiteeContent{
   174  						Owner: l[0],
   175  						Repo:  l[1],
   176  						Path:  strings.Join(l[2:], "/"),
   177  						Ref:   "", // use default branch
   178  					},
   179  				}, nil
   180  			}
   181  		default:
   182  			return "", nil, fmt.Errorf("git type repository only support github for now")
   183  		}
   184  	case "oss":
   185  		return TypeOss, &Content{
   186  			OssContent: OssContent{
   187  				EndPoint: URL.Host,
   188  				Bucket:   URL.Path,
   189  			},
   190  		}, nil
   191  	case "file":
   192  		return TypeLocal, &Content{
   193  			LocalContent: LocalContent{
   194  				AbsDir: URL.Path,
   195  			},
   196  		}, nil
   197  
   198  	}
   199  
   200  	return TypeUnknown, nil, nil
   201  }
   202  
   203  // ByteCountIEC convert number of bytes into readable string
   204  // borrowed from https://yourbasic.org/golang/formatting-byte-size-to-human-readable-format/
   205  func ByteCountIEC(b int64) string {
   206  	const unit = 1024
   207  	if b < unit {
   208  		return fmt.Sprintf("%d B", b)
   209  	}
   210  	div, exp := int64(unit), 0
   211  	for n := b / unit; n >= unit; n /= unit {
   212  		div *= unit
   213  		exp++
   214  	}
   215  	return fmt.Sprintf("%.1f %ciB",
   216  		float64(b)/float64(div), "KMGTPE"[exp])
   217  }
   218  
   219  // ParseGitlab will parse gitlab config from address
   220  func ParseGitlab(addr, repo string) (string, *Content, error) {
   221  	if !strings.Contains(addr, repo) {
   222  		return "", nil, errors.New("addon registry repo name invalid")
   223  	}
   224  
   225  	// We support two valid format:
   226  	// 1. https://example.gitlab.com/<owner>/<repo>
   227  	// 2. https://example.gitlab.com/<owner>/<repo>/tree/<branch>
   228  	URL, err := url.Parse(addr)
   229  	if err != nil {
   230  		return "", nil, err
   231  	}
   232  
   233  	arr := strings.Split(addr, repo)
   234  	owner := strings.Split(arr[0], URL.Host+"/")
   235  	if !strings.Contains(arr[1], "/") {
   236  		// https://example.gitlab.com/<owner>/<repo>
   237  		return TypeGitlab, &Content{
   238  			GitlabContent: GitlabContent{
   239  				Host:  URL.Scheme + "://" + URL.Host,
   240  				Owner: owner[1][:len(owner[1])-1],
   241  				Repo:  repo,
   242  				Ref:   "", // use default branch
   243  			},
   244  		}, nil
   245  	}
   246  
   247  	// https://example.gitlab.com/<owner>/<repo>/tree/<branch>
   248  	l := strings.Split(arr[1], "/")
   249  
   250  	return TypeGitlab, &Content{
   251  		GitlabContent: GitlabContent{
   252  			Host:  URL.Scheme + "://" + URL.Host,
   253  			Owner: owner[1][:len(owner[1])-1],
   254  			Repo:  repo,
   255  			Ref:   l[2],
   256  		},
   257  	}, nil
   258  }