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 }