mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 02:08:36 +00:00
Add Chef package registry (#22554)
This PR implements a [Chef registry](https://chef.io/) to manage cookbooks. This package type was a bit complicated because Chef uses RSA signed requests as authentication with the registry.   Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
134
modules/packages/chef/metadata.go
Normal file
134
modules/packages/chef/metadata.go
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package chef
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/validation"
|
||||
)
|
||||
|
||||
const (
|
||||
KeyBits = 4096
|
||||
SettingPublicPem = "chef.public_pem"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrMissingMetadataFile = util.NewInvalidArgumentErrorf("metadata.json file is missing")
|
||||
ErrInvalidName = util.NewInvalidArgumentErrorf("package name is invalid")
|
||||
ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid")
|
||||
|
||||
namePattern = regexp.MustCompile(`\A\S+\z`)
|
||||
versionPattern = regexp.MustCompile(`\A\d+\.\d+(?:\.\d+)?\z`)
|
||||
)
|
||||
|
||||
// Package represents a Chef package
|
||||
type Package struct {
|
||||
Name string
|
||||
Version string
|
||||
Metadata *Metadata
|
||||
}
|
||||
|
||||
// Metadata represents the metadata of a Chef package
|
||||
type Metadata struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
LongDescription string `json:"long_description,omitempty"`
|
||||
Author string `json:"author,omitempty"`
|
||||
License string `json:"license,omitempty"`
|
||||
RepositoryURL string `json:"repository_url,omitempty"`
|
||||
Dependencies map[string]string `json:"dependencies,omitempty"`
|
||||
}
|
||||
|
||||
type chefMetadata struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
LongDescription string `json:"long_description"`
|
||||
Maintainer string `json:"maintainer"`
|
||||
MaintainerEmail string `json:"maintainer_email"`
|
||||
License string `json:"license"`
|
||||
Platforms map[string]string `json:"platforms"`
|
||||
Dependencies map[string]string `json:"dependencies"`
|
||||
Providing map[string]string `json:"providing"`
|
||||
Recipes map[string]string `json:"recipes"`
|
||||
Version string `json:"version"`
|
||||
SourceURL string `json:"source_url"`
|
||||
IssuesURL string `json:"issues_url"`
|
||||
Privacy bool `json:"privacy"`
|
||||
ChefVersions [][]string `json:"chef_versions"`
|
||||
Gems [][]string `json:"gems"`
|
||||
EagerLoadLibraries bool `json:"eager_load_libraries"`
|
||||
}
|
||||
|
||||
// ParsePackage parses the Chef package file
|
||||
func ParsePackage(r io.Reader) (*Package, error) {
|
||||
gzr, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer gzr.Close()
|
||||
|
||||
tr := tar.NewReader(gzr)
|
||||
for {
|
||||
hd, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if hd.Typeflag != tar.TypeReg {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Count(hd.Name, "/") != 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if hd.FileInfo().Name() == "metadata.json" {
|
||||
return ParseChefMetadata(tr)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ErrMissingMetadataFile
|
||||
}
|
||||
|
||||
// ParseChefMetadata parses a metadata.json file to retrieve the metadata of a Chef package
|
||||
func ParseChefMetadata(r io.Reader) (*Package, error) {
|
||||
var cm chefMetadata
|
||||
if err := json.NewDecoder(r).Decode(&cm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !namePattern.MatchString(cm.Name) {
|
||||
return nil, ErrInvalidName
|
||||
}
|
||||
|
||||
if !versionPattern.MatchString(cm.Version) {
|
||||
return nil, ErrInvalidVersion
|
||||
}
|
||||
|
||||
if !validation.IsValidURL(cm.SourceURL) {
|
||||
cm.SourceURL = ""
|
||||
}
|
||||
|
||||
return &Package{
|
||||
Name: cm.Name,
|
||||
Version: cm.Version,
|
||||
Metadata: &Metadata{
|
||||
Description: cm.Description,
|
||||
LongDescription: cm.LongDescription,
|
||||
Author: cm.Maintainer,
|
||||
License: cm.License,
|
||||
RepositoryURL: cm.SourceURL,
|
||||
Dependencies: cm.Dependencies,
|
||||
},
|
||||
}, nil
|
||||
}
|
Reference in New Issue
Block a user