Skip to content

Commit

Permalink
add client repo setup scripts and endpoints
Browse files Browse the repository at this point in the history
Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
  • Loading branch information
Adphi committed Oct 5, 2023
1 parent cc1f9fd commit f0b61ef
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 2 deletions.
28 changes: 26 additions & 2 deletions pkg/packages/apk/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ import (
"io"
"net/http"
"path/filepath"
"strings"

"github.com/gorilla/mux"

"go.linka.cloud/artifact-registry/pkg/crypt/rsa"
"go.linka.cloud/artifact-registry/pkg/logger"
"go.linka.cloud/artifact-registry/pkg/packages"
"go.linka.cloud/artifact-registry/pkg/storage"
)
Expand All @@ -46,7 +48,7 @@ func (p *provider) Repository() storage.Repository {
return &repo{}
}

func (p *provider) DownloadKey(w http.ResponseWriter, r *http.Request) {
func (p *provider) downloadKey(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
s, ok := storage.FromContext(ctx)
if !ok {
Expand All @@ -65,8 +67,30 @@ func (p *provider) DownloadKey(w http.ResponseWriter, r *http.Request) {
io.Copy(w, bytes.NewReader(pub))
}

func (p *provider) setup(w http.ResponseWriter, r *http.Request) {
branch, repository := mux.Vars(r)["branch"], mux.Vars(r)["repository"]
user, pass, _ := r.BasicAuth()
scheme := "https"
if r.TLS == nil {
scheme = "http"
}
args := setupArgs{
User: user,
Password: pass,
Scheme: scheme,
Host: r.Host,
Path: strings.TrimSuffix(r.URL.Path, fmt.Sprintf("/%s/%s/setup", branch, repository)),
Branch: branch,
Repository: repository,
}
if err := scriptTemplate.Execute(w, args); err != nil {
logger.C(r.Context()).WithError(err).Error("failed to execute template")
}
}

func (p *provider) Register(m *mux.Router) {
m.HandleFunc("/{repo:.+}/{branch}/{repository}/key", p.DownloadKey).Methods(http.MethodGet)
m.HandleFunc("/{repo:.+}/{branch}/{repository}/key", p.downloadKey).Methods(http.MethodGet)
m.HandleFunc("/{repo:.+}/{branch}/{repository}/setup", p.setup).Methods(http.MethodGet)
m.HandleFunc("/{repo:.+}/{branch}/{repository}/upload", packages.Upload(func(r *http.Request, reader io.Reader, size int64, key string) (storage.Artifact, error) {
branch, repo := mux.Vars(r)["branch"], mux.Vars(r)["repository"]
return NewPackage(reader, branch, repo, size)
Expand Down
35 changes: 35 additions & 0 deletions pkg/packages/apk/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2023 Linka Cloud All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package apk

import (
_ "embed"
"text/template"
)

//go:embed setup.sh
var script string

var scriptTemplate = template.Must(template.New("setup.sh").Parse(script))

type setupArgs struct {
User string
Password string
Scheme string
Host string
Path string
Branch string
Repository string
}
69 changes: 69 additions & 0 deletions pkg/packages/apk/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/sh

# Copyright 2023 Linka Cloud All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

USER="{{ .User }}"
PASSWORD="{{ .Password }}"

SCHEME="{{ .Scheme }}"
REPO_HOST="{{ .Host }}"
REPO_PATH="{{ .Path }}"

BRANCH="{{ .Branch }}"
REPOSITORY="{{ .Repository }}"

set -e

[ -n "${DEBUG}" ] && set -x
[ "$1" = "--force" ] && FORCE=1

if [ -n "${USER}" ]; then
REPO_URL="${SCHEME}://${USER}:${PASSWORD}@${REPO_HOST}${REPO_PATH}/${BRANCH}/${REPOSITORY}"
else
REPO_URL="${SCHEME}://${REPO_HOST}${REPO_PATH}/${BRANCH}/${REPOSITORY}"
fi

if [ "$(id -u)" -ne 0 ]; then
echo "Please run as root or sudo"
exit 1
fi

if grep "${REPO_HOST}${REPO_PATH}/${BRANCH}/${REPOSITORY}" /etc/apk/repositories >/dev/null 2>&1 && [ -z "${FORCE}" ]; then
echo "Repository already configured."
echo "Use --force to overwrite."
exit 1
fi

if ! which curl >/dev/null 2>&1; then
echo "curl is required to setup the repository."
exit 1
fi

PATTERN="$(echo "${REPO_HOST}${REPO_PATH}/${BRANCH}/${REPOSITORY}"|sed 's/\//\\\//g')"
sed -i "/${PATTERN}/d" /etc/apk/repositories

if [ -n "${FORCE}" ]; then
NAME="$(curl -sIX GET "${REPO_URL}"/key|grep "Content-Disposition:"|cut -d'=' -f2|sed 's/\r$//')"
if [ -n "${NAME}" ]; then
rm -f "/etc/apk/keys/${NAME}"
fi
fi

(cd /etc/apk/keys && curl -sJO "${REPO_URL}/key")

echo "${REPO_URL}" >> /etc/apk/repositories

echo "apk repository setup complete."
echo "You can now run 'apk update' to update the package list or install packages directly using 'apk add --no-cache <package>'."
26 changes: 26 additions & 0 deletions pkg/packages/deb/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ package deb

import (
"context"
"fmt"
"io"
"net/http"
"path/filepath"
"strings"

"github.com/gorilla/mux"

"go.linka.cloud/artifact-registry/pkg/logger"
"go.linka.cloud/artifact-registry/pkg/packages"
"go.linka.cloud/artifact-registry/pkg/storage"
)
Expand All @@ -42,7 +45,30 @@ func (p *provider) Repository() storage.Repository {
return &repo{}
}

func (p *provider) setup(w http.ResponseWriter, r *http.Request) {
repo, dist, component := mux.Vars(r)["repo"], mux.Vars(r)["distribution"], mux.Vars(r)["component"]
user, pass, _ := r.BasicAuth()
scheme := "https"
if r.TLS == nil {
scheme = "http"
}
args := setupArgs{
Name: strings.Replace(repo, "/", "-", -1),
User: user,
Password: pass,
Scheme: scheme,
Host: r.Host,
Path: strings.TrimSuffix(r.URL.Path, fmt.Sprintf("/%s/%s/setup", dist, component)),
Dist: dist,
Component: component,
}
if err := scriptTemplate.Execute(w, args); err != nil {
logger.C(r.Context()).WithError(err).Error("failed to execute template")
}
}

func (p *provider) Register(m *mux.Router) {
m.HandleFunc("/{repo:.+}/{distribution}/{component}/setup", p.setup).Methods(http.MethodGet)
m.HandleFunc("/{repo:.+}/"+RepositoryPublicKey, packages.Download(func(r *http.Request) string {
return RepositoryPublicKey
})).Methods(http.MethodGet)
Expand Down
36 changes: 36 additions & 0 deletions pkg/packages/deb/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2023 Linka Cloud All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package deb

import (
_ "embed"
"text/template"
)

//go:embed setup.sh
var script string

var scriptTemplate = template.Must(template.New("setup.sh").Parse(script))

type setupArgs struct {
User string
Password string
Scheme string
Host string
Path string
Name string
Dist string
Component string
}
62 changes: 62 additions & 0 deletions pkg/packages/deb/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/bin/bash

# Copyright 2023 Linka Cloud All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -e

USER="{{ .User }}"
PASSWORD="{{ .Password }}"

SCHEME="{{ .Scheme }}"
REPO_HOST="{{ .Host }}"
REPO_PATH="{{ .Path }}"
REPO_NAME="{{ .Name }}"

DIST="{{ .Dist }}"
COMPONENT="{{ .Component }}"

[ -n "${DEBUG}" ] && set -x

if [ "$(id -u)" -ne 0 ]; then
echo "Please run as root or sudo"
exit 1
fi

if [ -f "/etc/apt/sources.list.d/${REPO_NAME}.list" ] && [ "$1" != "--force" ]; then
echo "Repository already configured."
echo "Use --force to overwrite."
exit 1
fi

if ! which curl >/dev/null 2>&1; then
echo "curl is required to setup the repository."
exit 1
fi

REPO="${SCHEME}://${REPO_HOST}${REPO_PATH}"

if [ -n "${USER}" ]; then
REPO_AUTH="${SCHEME}://${USER}:${PASSWORD}@${REPO_HOST}${REPO_PATH}"
echo "machine ${REPO} login $USER password $PASSWORD" > "/etc/apt/auth.conf.d/${REPO_NAME}.conf"
else
REPO_AUTH="${SCHEME}://${REPO_HOST}${REPO_PATH}/${DIST}/${COMPONENT}"
fi

curl -s "${REPO_AUTH}/repository.key" -o "/etc/apt/trusted.gpg.d/${REPO_NAME}.asc"
echo "deb ${REPO} ${DIST} ${COMPONENT}" > "/etc/apt/sources.list.d/${REPO_NAME}.list"

echo "deb repository setup complete."
echo "You can now run 'apt update' to update the package list."

22 changes: 22 additions & 0 deletions pkg/packages/rpm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/gorilla/mux"

"go.linka.cloud/artifact-registry/pkg/logger"
"go.linka.cloud/artifact-registry/pkg/packages"
"go.linka.cloud/artifact-registry/pkg/storage"
)
Expand All @@ -49,6 +50,7 @@ type provider struct{}

func (p *provider) Register(r *mux.Router) {
r.HandleFunc("/{repo:.+}.repo", p.config).Methods(http.MethodGet)
r.HandleFunc("/{repo:.+}/setup", p.setup).Methods(http.MethodGet)
r.HandleFunc("/{repo:.+}/upload", p.upload()).Methods(http.MethodPut)
r.HandleFunc("/{repo:.+}/repodata/{filename}", p.download()).Methods(http.MethodGet)
r.HandleFunc("/{repo:.+}/{filename}", p.download()).Methods(http.MethodGet)
Expand Down Expand Up @@ -80,6 +82,26 @@ func (p *provider) config(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf(definition, strings.NewReplacer("/", "-").Replace(name), url, RepositoryPublicKey)))
}

func (p *provider) setup(w http.ResponseWriter, r *http.Request) {
repo := mux.Vars(r)["repo"]
user, pass, _ := r.BasicAuth()
scheme := "https"
if r.TLS == nil {
scheme = "http"
}
args := setupArgs{
Name: strings.Replace(repo, "/", "-", -1),
User: user,
Password: pass,
Scheme: scheme,
Host: r.Host,
Path: strings.TrimSuffix(r.URL.Path, "/setup"),
}
if err := scriptTemplate.Execute(w, args); err != nil {
logger.C(r.Context()).WithError(err).Error("failed to execute template")
}
}

func (p *provider) upload() http.HandlerFunc {
return packages.Upload(func(r *http.Request, reader io.Reader, size int64, key string) (storage.Artifact, error) {
return NewPackage(reader, size, key)
Expand Down
34 changes: 34 additions & 0 deletions pkg/packages/rpm/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2023 Linka Cloud All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package rpm

import (
_ "embed"
"text/template"
)

//go:embed setup.sh
var script string

var scriptTemplate = template.Must(template.New("setup.sh").Parse(script))

type setupArgs struct {
User string
Password string
Scheme string
Host string
Path string
Name string
}
Loading

0 comments on commit f0b61ef

Please sign in to comment.