working commit
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
MAX_SIZE=1024 # 1 MB limit in KB
|
||||
for file in $(git diff --cached --name-only --diff-filter=ACM); do
|
||||
if [ ! -e "$file" ]; then continue; fi
|
||||
size=$(du -k "$file" | cut -f1)
|
||||
if [ $size -gt $MAX_SIZE ]; then
|
||||
echo "Error: File $file is larger than the allowed size of $((MAX_SIZE / 1024)) MB."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
status=0
|
||||
|
||||
for file in $(git diff --cached --name-only | grep -E '\.go$'); do
|
||||
badfile=$(gofmt -l "$file")
|
||||
if test -n "$badfile" ; then
|
||||
echo "Error: file needs gofmt: $badfile"
|
||||
status=1
|
||||
fi
|
||||
done
|
||||
|
||||
# If any files were not formatted, exit with a non-zero status to abort the commit.
|
||||
if [ "$status" -ne 0 ]; then
|
||||
echo "git pre-commit check failed: some Go files are not formatted."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
exit 0
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
*~
|
||||
autom4te.cache
|
||||
Makefile
|
||||
config.status
|
||||
config.log
|
||||
cmd/mbased/mbased
|
||||
cmd/mbasectl/mbasectl
|
||||
*.db
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
*.tar.*
|
||||
*.tmp.*
|
||||
*.tar
|
||||
*.bin
|
||||
tmp
|
||||
mbased
|
||||
mbasectl
|
||||
DIST
|
||||
*.tar.gz
|
||||
*.deb
|
||||
*.rpm
|
||||
mbased.service
|
||||
variant.go
|
||||
initrc/mbased
|
||||
@@ -0,0 +1,26 @@
|
||||
FROM alpine:3.23 AS builder
|
||||
|
||||
RUN apk --no-cache add make binutils gcc libc-dev automake autoconf curl
|
||||
RUN curl -o /usr/local/lib/go.tar.gz https://dl.google.com/go/go1.26.2.linux-amd64.tar.gz
|
||||
RUN cd /usr/local/lib && tar xzf go.tar.gz
|
||||
RUN cd /usr/local/bin && ln -sf ../lib/go/bin/* .
|
||||
|
||||
WORKDIR /app/src/
|
||||
COPY go.mod go.sum .
|
||||
COPY . .
|
||||
|
||||
RUN ./configure --prefix=/app
|
||||
RUN make all install
|
||||
RUN make clean
|
||||
RUN rm -rf /app/src
|
||||
|
||||
FROM alpine:3.23 AS runner
|
||||
|
||||
COPY --from=builder /app /app
|
||||
RUN chmod 1777 /var
|
||||
RUN mkdir -p /app/etc/mbase
|
||||
RUN touch /app/etc/mbase/mbased.yaml
|
||||
WORKDIR /app
|
||||
|
||||
#USER daemon:daemon
|
||||
ENTRYPOINT ["/app/sbin/mbased", "--asDaemon=false"]
|
||||
+439
@@ -0,0 +1,439 @@
|
||||
|
||||
Attribution-NonCommercial-ShareAlike 4.0 International
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||
does not provide legal services or legal advice. Distribution of
|
||||
Creative Commons public licenses does not create a lawyer-client or
|
||||
other relationship. Creative Commons makes its licenses and related
|
||||
information available on an "as-is" basis. Creative Commons gives no
|
||||
warranties regarding its licenses, any material licensed under their
|
||||
terms and conditions, or any related information. Creative Commons
|
||||
disclaims all liability for damages resulting from their use to the
|
||||
fullest extent possible.
|
||||
|
||||
Using Creative Commons Public Licenses
|
||||
|
||||
Creative Commons public licenses provide a standard set of terms and
|
||||
conditions that creators and other rights holders may use to share
|
||||
original works of authorship and other material subject to copyright
|
||||
and certain other rights specified in the public license below. The
|
||||
following considerations are for informational purposes only, are not
|
||||
exhaustive, and do not form part of our licenses.
|
||||
|
||||
Considerations for licensors: Our public licenses are
|
||||
intended for use by those authorized to give the public
|
||||
permission to use material in ways otherwise restricted by
|
||||
copyright and certain other rights. Our licenses are
|
||||
irrevocable. Licensors should read and understand the terms
|
||||
and conditions of the license they choose before applying it.
|
||||
Licensors should also secure all rights necessary before
|
||||
applying our licenses so that the public can reuse the
|
||||
material as expected. Licensors should clearly mark any
|
||||
material not subject to the license. This includes other CC-
|
||||
licensed material, or material used under an exception or
|
||||
limitation to copyright. More considerations for licensors:
|
||||
wiki.creativecommons.org/Considerations_for_licensors
|
||||
|
||||
Considerations for the public: By using one of our public
|
||||
licenses, a licensor grants the public permission to use the
|
||||
licensed material under specified terms and conditions. If
|
||||
the licensor's permission is not necessary for any reason--for
|
||||
example, because of any applicable exception or limitation to
|
||||
copyright--then that use is not regulated by the license. Our
|
||||
licenses grant only permissions under copyright and certain
|
||||
other rights that a licensor has authority to grant. Use of
|
||||
the licensed material may still be restricted for other
|
||||
reasons, including because others have copyright or other
|
||||
rights in the material. A licensor may make special requests,
|
||||
such as asking that all changes be marked or described.
|
||||
Although not required by our licenses, you are encouraged to
|
||||
respect those requests where reasonable. More considerations
|
||||
for the public:
|
||||
wiki.creativecommons.org/Considerations_for_licensees
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
||||
Public License
|
||||
|
||||
By exercising the Licensed Rights (defined below), You accept and agree
|
||||
to be bound by the terms and conditions of this Creative Commons
|
||||
Attribution-NonCommercial-ShareAlike 4.0 International Public License
|
||||
("Public License"). To the extent this Public License may be
|
||||
interpreted as a contract, You are granted the Licensed Rights in
|
||||
consideration of Your acceptance of these terms and conditions, and the
|
||||
Licensor grants You such rights in consideration of benefits the
|
||||
Licensor receives from making the Licensed Material available under
|
||||
these terms and conditions.
|
||||
|
||||
|
||||
Section 1 -- Definitions.
|
||||
|
||||
a. Adapted Material means material subject to Copyright and Similar
|
||||
Rights that is derived from or based upon the Licensed Material
|
||||
and in which the Licensed Material is translated, altered,
|
||||
arranged, transformed, or otherwise modified in a manner requiring
|
||||
permission under the Copyright and Similar Rights held by the
|
||||
Licensor. For purposes of this Public License, where the Licensed
|
||||
Material is a musical work, performance, or sound recording,
|
||||
Adapted Material is always produced where the Licensed Material is
|
||||
synched in timed relation with a moving image.
|
||||
|
||||
b. Adapter's License means the license You apply to Your Copyright
|
||||
and Similar Rights in Your contributions to Adapted Material in
|
||||
accordance with the terms and conditions of this Public License.
|
||||
|
||||
c. BY-NC-SA Compatible License means a license listed at
|
||||
creativecommons.org/compatiblelicenses, approved by Creative
|
||||
Commons as essentially the equivalent of this Public License.
|
||||
|
||||
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||
closely related to copyright including, without limitation,
|
||||
performance, broadcast, sound recording, and Sui Generis Database
|
||||
Rights, without regard to how the rights are labeled or
|
||||
categorized. For purposes of this Public License, the rights
|
||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||
Rights.
|
||||
|
||||
e. Effective Technological Measures means those measures that, in the
|
||||
absence of proper authority, may not be circumvented under laws
|
||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||
Treaty adopted on December 20, 1996, and/or similar international
|
||||
agreements.
|
||||
|
||||
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||
any other exception or limitation to Copyright and Similar Rights
|
||||
that applies to Your use of the Licensed Material.
|
||||
|
||||
g. License Elements means the license attributes listed in the name
|
||||
of a Creative Commons Public License. The License Elements of this
|
||||
Public License are Attribution, NonCommercial, and ShareAlike.
|
||||
|
||||
h. Licensed Material means the artistic or literary work, database,
|
||||
or other material to which the Licensor applied this Public
|
||||
License.
|
||||
|
||||
i. Licensed Rights means the rights granted to You subject to the
|
||||
terms and conditions of this Public License, which are limited to
|
||||
all Copyright and Similar Rights that apply to Your use of the
|
||||
Licensed Material and that the Licensor has authority to license.
|
||||
|
||||
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||
under this Public License.
|
||||
|
||||
k. NonCommercial means not primarily intended for or directed towards
|
||||
commercial advantage or monetary compensation. For purposes of
|
||||
this Public License, the exchange of the Licensed Material for
|
||||
other material subject to Copyright and Similar Rights by digital
|
||||
file-sharing or similar means is NonCommercial provided there is
|
||||
no payment of monetary compensation in connection with the
|
||||
exchange.
|
||||
|
||||
l. Share means to provide material to the public by any means or
|
||||
process that requires permission under the Licensed Rights, such
|
||||
as reproduction, public display, public performance, distribution,
|
||||
dissemination, communication, or importation, and to make material
|
||||
available to the public including in ways that members of the
|
||||
public may access the material from a place and at a time
|
||||
individually chosen by them.
|
||||
|
||||
m. Sui Generis Database Rights means rights other than copyright
|
||||
resulting from Directive 96/9/EC of the European Parliament and of
|
||||
the Council of 11 March 1996 on the legal protection of databases,
|
||||
as amended and/or succeeded, as well as other essentially
|
||||
equivalent rights anywhere in the world.
|
||||
|
||||
n. You means the individual or entity exercising the Licensed Rights
|
||||
under this Public License. Your has a corresponding meaning.
|
||||
|
||||
|
||||
Section 2 -- Scope.
|
||||
|
||||
a. License grant.
|
||||
|
||||
1. Subject to the terms and conditions of this Public License,
|
||||
the Licensor hereby grants You a worldwide, royalty-free,
|
||||
non-sublicensable, non-exclusive, irrevocable license to
|
||||
exercise the Licensed Rights in the Licensed Material to:
|
||||
|
||||
a. reproduce and Share the Licensed Material, in whole or
|
||||
in part, for NonCommercial purposes only; and
|
||||
|
||||
b. produce, reproduce, and Share Adapted Material for
|
||||
NonCommercial purposes only.
|
||||
|
||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||
Exceptions and Limitations apply to Your use, this Public
|
||||
License does not apply, and You do not need to comply with
|
||||
its terms and conditions.
|
||||
|
||||
3. Term. The term of this Public License is specified in Section
|
||||
6(a).
|
||||
|
||||
4. Media and formats; technical modifications allowed. The
|
||||
Licensor authorizes You to exercise the Licensed Rights in
|
||||
all media and formats whether now known or hereafter created,
|
||||
and to make technical modifications necessary to do so. The
|
||||
Licensor waives and/or agrees not to assert any right or
|
||||
authority to forbid You from making technical modifications
|
||||
necessary to exercise the Licensed Rights, including
|
||||
technical modifications necessary to circumvent Effective
|
||||
Technological Measures. For purposes of this Public License,
|
||||
simply making modifications authorized by this Section 2(a)
|
||||
(4) never produces Adapted Material.
|
||||
|
||||
5. Downstream recipients.
|
||||
|
||||
a. Offer from the Licensor -- Licensed Material. Every
|
||||
recipient of the Licensed Material automatically
|
||||
receives an offer from the Licensor to exercise the
|
||||
Licensed Rights under the terms and conditions of this
|
||||
Public License.
|
||||
|
||||
b. Additional offer from the Licensor -- Adapted Material.
|
||||
Every recipient of Adapted Material from You
|
||||
automatically receives an offer from the Licensor to
|
||||
exercise the Licensed Rights in the Adapted Material
|
||||
under the conditions of the Adapter's License You apply.
|
||||
|
||||
c. No downstream restrictions. You may not offer or impose
|
||||
any additional or different terms or conditions on, or
|
||||
apply any Effective Technological Measures to, the
|
||||
Licensed Material if doing so restricts exercise of the
|
||||
Licensed Rights by any recipient of the Licensed
|
||||
Material.
|
||||
|
||||
6. No endorsement. Nothing in this Public License constitutes or
|
||||
may be construed as permission to assert or imply that You
|
||||
are, or that Your use of the Licensed Material is, connected
|
||||
with, or sponsored, endorsed, or granted official status by,
|
||||
the Licensor or others designated to receive attribution as
|
||||
provided in Section 3(a)(1)(A)(i).
|
||||
|
||||
b. Other rights.
|
||||
|
||||
1. Moral rights, such as the right of integrity, are not
|
||||
licensed under this Public License, nor are publicity,
|
||||
privacy, and/or other similar personality rights; however, to
|
||||
the extent possible, the Licensor waives and/or agrees not to
|
||||
assert any such rights held by the Licensor to the limited
|
||||
extent necessary to allow You to exercise the Licensed
|
||||
Rights, but not otherwise.
|
||||
|
||||
2. Patent and trademark rights are not licensed under this
|
||||
Public License.
|
||||
|
||||
3. To the extent possible, the Licensor waives any right to
|
||||
collect royalties from You for the exercise of the Licensed
|
||||
Rights, whether directly or through a collecting society
|
||||
under any voluntary or waivable statutory or compulsory
|
||||
licensing scheme. In all other cases the Licensor expressly
|
||||
reserves any right to collect such royalties, including when
|
||||
the Licensed Material is used other than for NonCommercial
|
||||
purposes.
|
||||
|
||||
|
||||
Section 3 -- License Conditions.
|
||||
|
||||
Your exercise of the Licensed Rights is expressly made subject to the
|
||||
following conditions.
|
||||
|
||||
a. Attribution.
|
||||
|
||||
1. If You Share the Licensed Material (including in modified
|
||||
form), You must:
|
||||
|
||||
a. retain the following if it is supplied by the Licensor
|
||||
with the Licensed Material:
|
||||
|
||||
i. identification of the creator(s) of the Licensed
|
||||
Material and any others designated to receive
|
||||
attribution, in any reasonable manner requested by
|
||||
the Licensor (including by pseudonym if
|
||||
designated);
|
||||
|
||||
ii. a copyright notice;
|
||||
|
||||
iii. a notice that refers to this Public License;
|
||||
|
||||
iv. a notice that refers to the disclaimer of
|
||||
warranties;
|
||||
|
||||
v. a URI or hyperlink to the Licensed Material to the
|
||||
extent reasonably practicable;
|
||||
|
||||
b. indicate if You modified the Licensed Material and
|
||||
retain an indication of any previous modifications; and
|
||||
|
||||
c. indicate the Licensed Material is licensed under this
|
||||
Public License, and include the text of, or the URI or
|
||||
hyperlink to, this Public License.
|
||||
|
||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||
reasonable manner based on the medium, means, and context in
|
||||
which You Share the Licensed Material. For example, it may be
|
||||
reasonable to satisfy the conditions by providing a URI or
|
||||
hyperlink to a resource that includes the required
|
||||
information.
|
||||
3. If requested by the Licensor, You must remove any of the
|
||||
information required by Section 3(a)(1)(A) to the extent
|
||||
reasonably practicable.
|
||||
|
||||
b. ShareAlike.
|
||||
|
||||
In addition to the conditions in Section 3(a), if You Share
|
||||
Adapted Material You produce, the following conditions also apply.
|
||||
|
||||
1. The Adapter's License You apply must be a Creative Commons
|
||||
license with the same License Elements, this version or
|
||||
later, or a BY-NC-SA Compatible License.
|
||||
|
||||
2. You must include the text of, or the URI or hyperlink to, the
|
||||
Adapter's License You apply. You may satisfy this condition
|
||||
in any reasonable manner based on the medium, means, and
|
||||
context in which You Share Adapted Material.
|
||||
|
||||
3. You may not offer or impose any additional or different terms
|
||||
or conditions on, or apply any Effective Technological
|
||||
Measures to, Adapted Material that restrict exercise of the
|
||||
rights granted under the Adapter's License You apply.
|
||||
|
||||
|
||||
Section 4 -- Sui Generis Database Rights.
|
||||
|
||||
Where the Licensed Rights include Sui Generis Database Rights that
|
||||
apply to Your use of the Licensed Material:
|
||||
|
||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||
to extract, reuse, reproduce, and Share all or a substantial
|
||||
portion of the contents of the database for NonCommercial purposes
|
||||
only;
|
||||
|
||||
b. if You include all or a substantial portion of the database
|
||||
contents in a database in which You have Sui Generis Database
|
||||
Rights, then the database in which You have Sui Generis Database
|
||||
Rights (but not its individual contents) is Adapted Material,
|
||||
including for purposes of Section 3(b); and
|
||||
|
||||
c. You must comply with the conditions in Section 3(a) if You Share
|
||||
all or a substantial portion of the contents of the database.
|
||||
|
||||
For the avoidance of doubt, this Section 4 supplements and does not
|
||||
replace Your obligations under this Public License where the Licensed
|
||||
Rights include other Copyright and Similar Rights.
|
||||
|
||||
|
||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||
|
||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||
|
||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
c. The disclaimer of warranties and limitation of liability provided
|
||||
above shall be interpreted in a manner that, to the extent
|
||||
possible, most closely approximates an absolute disclaimer and
|
||||
waiver of all liability.
|
||||
|
||||
|
||||
Section 6 -- Term and Termination.
|
||||
|
||||
a. This Public License applies for the term of the Copyright and
|
||||
Similar Rights licensed here. However, if You fail to comply with
|
||||
this Public License, then Your rights under this Public License
|
||||
terminate automatically.
|
||||
|
||||
b. Where Your right to use the Licensed Material has terminated under
|
||||
Section 6(a), it reinstates:
|
||||
|
||||
1. automatically as of the date the violation is cured, provided
|
||||
it is cured within 30 days of Your discovery of the
|
||||
violation; or
|
||||
|
||||
2. upon express reinstatement by the Licensor.
|
||||
|
||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||
right the Licensor may have to seek remedies for Your violations
|
||||
of this Public License.
|
||||
|
||||
c. For the avoidance of doubt, the Licensor may also offer the
|
||||
Licensed Material under separate terms or conditions or stop
|
||||
distributing the Licensed Material at any time; however, doing so
|
||||
will not terminate this Public License.
|
||||
|
||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||
License.
|
||||
|
||||
|
||||
Section 7 -- Other Terms and Conditions.
|
||||
|
||||
a. The Licensor shall not be bound by any additional or different
|
||||
terms or conditions communicated by You unless expressly agreed.
|
||||
|
||||
b. Any arrangements, understandings, or agreements regarding the
|
||||
Licensed Material not stated herein are separate from and
|
||||
independent of the terms and conditions of this Public License.
|
||||
|
||||
|
||||
Section 8 -- Interpretation.
|
||||
|
||||
a. For the avoidance of doubt, this Public License does not, and
|
||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||
conditions on any use of the Licensed Material that could lawfully
|
||||
be made without permission under this Public License.
|
||||
|
||||
b. To the extent possible, if any provision of this Public License is
|
||||
deemed unenforceable, it shall be automatically reformed to the
|
||||
minimum extent necessary to make it enforceable. If the provision
|
||||
cannot be reformed, it shall be severed from this Public License
|
||||
without affecting the enforceability of the remaining terms and
|
||||
conditions.
|
||||
|
||||
c. No term or condition of this Public License will be waived and no
|
||||
failure to comply consented to unless expressly agreed to by the
|
||||
Licensor.
|
||||
|
||||
d. Nothing in this Public License constitutes or may be interpreted
|
||||
as a limitation upon, or waiver of, any privileges and immunities
|
||||
that apply to the Licensor or You, including from the legal
|
||||
processes of any jurisdiction or authority.
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons is not a party to its public
|
||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||
its public licenses to material it publishes and in those instances
|
||||
will be considered the “Licensor.” The text of the Creative Commons
|
||||
public licenses is dedicated to the public domain under the CC0 Public
|
||||
Domain Dedication. Except for the limited purpose of indicating that
|
||||
material is shared under a Creative Commons public license or as
|
||||
otherwise permitted by the Creative Commons policies published at
|
||||
creativecommons.org/policies, Creative Commons does not authorize the
|
||||
use of the trademark "Creative Commons" or any other trademark or logo
|
||||
of Creative Commons without its prior written consent including,
|
||||
without limitation, in connection with any unauthorized modifications
|
||||
to any of its public licenses or any other arrangements,
|
||||
understandings, or agreements concerning use of licensed material. For
|
||||
the avoidance of doubt, this paragraph does not form part of the
|
||||
public licenses.
|
||||
|
||||
Creative Commons may be contacted at creativecommons.org.
|
||||
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
|
||||
|
||||
SUBDIRS = mans
|
||||
|
||||
GOFLAGS= -v
|
||||
bin_PROGRAMS = mproxyctl
|
||||
sbin_PROGRAMS = mproxyd
|
||||
|
||||
mproxyctl_SOURCES = \
|
||||
cmd/mproxyctl/main.go
|
||||
|
||||
EXTRA_mproxyctl_SOURCES = \
|
||||
cmd/mproxyctl/util/util.go
|
||||
|
||||
mproxyd_SOURCES = cmd/mproxyd/main.go
|
||||
|
||||
EXTRA_mproxyd_SOURCES = cmd/mproxyd/starter/starter.go
|
||||
|
||||
mproxyctl$(EXEEXT): $(mproxyctl_SOURCES) $(EXTRA_mproxyctl_SOURCES) $(EXTRA_mbased_SOURCES)
|
||||
env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o mproxyctl$(EXEEXT) $(mproxyctl_SOURCES)
|
||||
|
||||
mproxyd$(EXEEXT): $(mproxyd_SOURCES) $(EXTRA_mproxyd_SOURCES)
|
||||
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mproxyd$(EXEEXT) $(mproxyd_SOURCES)
|
||||
|
||||
run: $(mproxyd_SOURCES)
|
||||
cd cmd/mproxyd && env CGO_ENABLED=1 $(GO) run . --asDaemon=false --port=443
|
||||
|
||||
CWD=$(shell pwd)
|
||||
|
||||
EXTRA_mproxyd_SOURCES += \
|
||||
app/config/config.go \
|
||||
app/config/variant.go \
|
||||
app/handler/aaafunc.go \
|
||||
app/handler/account.go \
|
||||
app/handler/grant.go \
|
||||
app/handler/handler.go \
|
||||
app/handler/notfound.go \
|
||||
app/handler/response.go \
|
||||
app/handler/service.go \
|
||||
app/locker/locker.go \
|
||||
app/logger/logger.go \
|
||||
app/router/bindobj.go \
|
||||
app/router/context.go \
|
||||
app/router/corsmw.go \
|
||||
app/router/loggingmw.go \
|
||||
app/router/pathc.go \
|
||||
app/router/recovermw.go \
|
||||
app/router/router.go \
|
||||
app/server/server.go \
|
||||
app/server/listen.go \
|
||||
app/service/service.go \
|
||||
\
|
||||
app/servoper/operator.go \
|
||||
app/servoper/service.go \
|
||||
\
|
||||
pkg/auxhttp/basic.go \
|
||||
pkg/auxhttp/crange.go \
|
||||
pkg/auxpwd/passwd.go \
|
||||
pkg/auxtool/cleandir.go \
|
||||
pkg/auxtool/fileex.go \
|
||||
pkg/auxtool/randstr.go \
|
||||
pkg/auxtool/tmpfile.go \
|
||||
pkg/auxtool/unixnow.go \
|
||||
pkg/auxutar/utar.go \
|
||||
pkg/auxuuid/uuid.go \
|
||||
pkg/auxx509/x509cert.go \
|
||||
pkg/terms/terms.go
|
||||
|
||||
|
||||
EXTRA_DIST = vendor/* \
|
||||
\
|
||||
Containerfile \
|
||||
go.mod \
|
||||
go.sum \
|
||||
LICENSE.txt \
|
||||
README.md \
|
||||
DEVEL.md \
|
||||
\
|
||||
debian/changelog.in \
|
||||
debian/compat \
|
||||
debian/control.in \
|
||||
debian/files \
|
||||
debian/.gitignore \
|
||||
debian/mproxy-control.install \
|
||||
debian/mproxy-control.postinst \
|
||||
debian/mproxy-control.postrm \
|
||||
debian/mproxy-control.preinst \
|
||||
debian/mproxy-control.prerm \
|
||||
debian/mproxy-service.install \
|
||||
debian/mproxy-service.postinst \
|
||||
debian/mproxy-service.postrm \
|
||||
debian/mproxy-service.preinst \
|
||||
debian/mproxy-service.prerm \
|
||||
debian/patches/series \
|
||||
debian/README.Debian \
|
||||
debian/rules \
|
||||
debian/source/format \
|
||||
debian/source/include-binaries \
|
||||
debian/watch \
|
||||
\
|
||||
initrc/.gitignore \
|
||||
initrc/mproxyd.in \
|
||||
initrc/mproxyd.service.in \
|
||||
\
|
||||
app/router/pathc_test.go \
|
||||
app/router/router_test.go \
|
||||
pkg/auxpwd/passwd_test.go \
|
||||
pkg/auxx509/x509cert_test.go
|
||||
|
||||
format:
|
||||
@dirs=$$($(FIND) $(CWD)/app $(CWD)/cmd $(CWD)/pkg \
|
||||
-name '*.go' | $(XARGS) -n1 dirname | $(SORT) | $(UNIQ)); \
|
||||
for dir in $$dirs;do \
|
||||
(echo "====$$dir===="; cd $$dir && $(GO) fmt .); \
|
||||
done
|
||||
|
||||
DIST_DIR= $(shell pwd)/DIST
|
||||
BUILD_DIR= $(shell pwd)/BUILD
|
||||
|
||||
IMAGE_REPO = localhost
|
||||
IMAGE_NAME = $(PACKAGE_NAME):$(PACKAGE_VERSION)
|
||||
IMAGE_TARNAME = $(PACKAGE_NAME)-$(PACKAGE_VERSION).img
|
||||
IMAGE_CONTAINERFILE = Containerfile
|
||||
|
||||
image:: build-image
|
||||
build-image: clean
|
||||
# $(GO) mod vendor
|
||||
mkdir -p $(DIST_DIR)
|
||||
$(SUDO) $(PODMAN) build -t $(IMAGE_REPO)/$(IMAGE_NAME) -f $(IMAGE_CONTAINERFILE) .
|
||||
rm -f $(DIST_DIR)/$(IMAGE_TARNAME)
|
||||
$(SUDO) $(PODMAN) image save $(IMAGE_REPO)/$(IMAGE_NAME) --format oci-archive \
|
||||
-o $(DIST_DIR)/$(IMAGE_TARNAME)
|
||||
username=$$(whoami); \
|
||||
$(SUDO) chown $$username $(DIST_DIR)/$(IMAGE_TARNAME)
|
||||
# rm -rf vendor
|
||||
|
||||
$(DIST_ARCHIVES): dist
|
||||
|
||||
package:: debian-package
|
||||
debian-package: $(DIST_ARCHIVES)
|
||||
mkdir -p $(BUILD_DIR)
|
||||
mv $(DIST_ARCHIVES) $(BUILD_DIR)
|
||||
cd $(BUILD_DIR) && $(AMTAR) -xf $(DIST_ARCHIVES)
|
||||
cd $(BUILD_DIR)/$(distdir) && ./configure --prefix=/usr
|
||||
cd $(BUILD_DIR)/$(distdir) && $(MAKE) clean
|
||||
cd $(BUILD_DIR)/$(distdir) && $(DPKGSOURCE) -i --before-build .
|
||||
cd $(BUILD_DIR)/$(distdir) && $(DBUILDPACKAGE) -nc -us -uc -ui -i -b
|
||||
mkdir -p $(DIST_DIR)
|
||||
$(CP) $(BUILD_DIR)/*.deb $(DIST_DIR)
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
FREEBSD_LOCALBASE = /usr/local
|
||||
FREEBSD_RCDIR = $(FREEBSD_LOCALBASE)/etc/rc.d
|
||||
LINUX_SYSTEMDDIR = /lib/systemd/system
|
||||
|
||||
install-data-local:
|
||||
test -z $(DESTDIR)$(srv_confdir) || $(MKDIR_P) $(DESTDIR)$(srv_confdir)
|
||||
test -z $(DESTDIR)$(srv_logdir) || $(MKDIR_P) $(DESTDIR)$(srv_logdir)
|
||||
test -z $(DESTDIR)$(srv_rundir) || $(MKDIR_P) $(DESTDIR)$(srv_rundir)
|
||||
test -z $(DESTDIR)$(srv_datadir) || $(MKDIR_P) $(DESTDIR)$(srv_datadir)
|
||||
if FREEBSD_OS
|
||||
test -z $(DESTDIR)$(FREEBSD_RCDIR) || $(MKDIR_P) $(DESTDIR)$(FREEBSD_RCDIR)
|
||||
$(INSTALL_DATA) initrc/mproxyd $(DESTDIR)$(FREEBSD_RCDIR)
|
||||
chmod a+x $(DESTDIR)$(FREEBSD_RCDIR)/mproxyd
|
||||
endif
|
||||
if LINUX_OS
|
||||
if SYSTEMD
|
||||
test -z $(DESTDIR)$(LINUX_SYSTEMDDIR) || $(MKDIR_P) $(DESTDIR)$(LINUX_SYSTEMDDIR)
|
||||
$(INSTALL_DATA) initrc/mproxyd.service $(DESTDIR)$(LINUX_SYSTEMDDIR)
|
||||
endif
|
||||
endif
|
||||
|
||||
clean-local:
|
||||
$(FIND) $(CWD) -name '*~' | $(XARGS) rm -f
|
||||
rm -rf autom4te.cache
|
||||
rm -f cmd/mproxyd/mproxyd
|
||||
rm -f cmd/mproxyctl/mproxyctl
|
||||
# rm -rf tmp/
|
||||
|
||||
distclean-local:
|
||||
rm -rf autom4te.cache
|
||||
rm -rf $(DIST_DIR)
|
||||
rm -rf tmp/
|
||||
|
||||
|
||||
+1081
File diff suppressed because it is too large
Load Diff
Vendored
+977
@@ -0,0 +1,977 @@
|
||||
# generated automatically by aclocal 1.17 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.72],,
|
||||
[m4_warning([this file was generated for autoconf 2.72.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
|
||||
|
||||
# Copyright (C) 2002-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_AUTOMAKE_VERSION(VERSION)
|
||||
# ----------------------------
|
||||
# Automake X.Y traces this macro to ensure aclocal.m4 has been
|
||||
# generated from the m4 files accompanying Automake X.Y.
|
||||
# (This private macro should not be called outside this file.)
|
||||
AC_DEFUN([AM_AUTOMAKE_VERSION],
|
||||
[am__api_version='1.17'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.17], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
# _AM_AUTOCONF_VERSION(VERSION)
|
||||
# -----------------------------
|
||||
# aclocal traces this macro to find the Autoconf version.
|
||||
# This is a private macro too. Using m4_define simplifies
|
||||
# the logic in aclocal, which can simply ignore this definition.
|
||||
m4_define([_AM_AUTOCONF_VERSION], [])
|
||||
|
||||
# AM_SET_CURRENT_AUTOMAKE_VERSION
|
||||
# -------------------------------
|
||||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.17])dnl
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
|
||||
|
||||
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
|
||||
# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
|
||||
# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
|
||||
#
|
||||
# Of course, Automake must honor this variable whenever it calls a
|
||||
# tool from the auxiliary directory. The problem is that $srcdir (and
|
||||
# therefore $ac_aux_dir as well) can be either absolute or relative,
|
||||
# depending on how configure is run. This is pretty annoying, since
|
||||
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
|
||||
# source directory, any form will work fine, but in subdirectories a
|
||||
# relative path needs to be adjusted first.
|
||||
#
|
||||
# $ac_aux_dir/missing
|
||||
# fails when called from a subdirectory if $ac_aux_dir is relative
|
||||
# $top_srcdir/$ac_aux_dir/missing
|
||||
# fails if $ac_aux_dir is absolute,
|
||||
# fails when called from a subdirectory in a VPATH build with
|
||||
# a relative $ac_aux_dir
|
||||
#
|
||||
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
|
||||
# are both prefixed by $srcdir. In an in-source build this is usually
|
||||
# harmless because $srcdir is '.', but things will broke when you
|
||||
# start a VPATH build or use an absolute $srcdir.
|
||||
#
|
||||
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
|
||||
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
|
||||
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
|
||||
# and then we would define $MISSING as
|
||||
# MISSING="\${SHELL} $am_aux_dir/missing"
|
||||
# This will work as long as MISSING is not called from configure, because
|
||||
# unfortunately $(top_srcdir) has no meaning in configure.
|
||||
# However there are other variables, like CC, which are often used in
|
||||
# configure, and could therefore not use this "fixed" $ac_aux_dir.
|
||||
#
|
||||
# Another solution, used here, is to always expand $ac_aux_dir to an
|
||||
# absolute PATH. The drawback is that using absolute paths prevent a
|
||||
# configured tree to be moved without reconfiguration.
|
||||
|
||||
AC_DEFUN([AM_AUX_DIR_EXPAND],
|
||||
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
|
||||
# Expand $ac_aux_dir to an absolute path.
|
||||
am_aux_dir=`cd "$ac_aux_dir" && pwd`
|
||||
])
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
||||
# -------------------------------------
|
||||
# Define a conditional.
|
||||
AC_DEFUN([AM_CONDITIONAL],
|
||||
[AC_PREREQ([2.52])dnl
|
||||
m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
|
||||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
|
||||
AC_SUBST([$1_TRUE])dnl
|
||||
AC_SUBST([$1_FALSE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
|
||||
m4_define([_AM_COND_VALUE_$1], [$2])dnl
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
else
|
||||
$1_TRUE='#'
|
||||
$1_FALSE=
|
||||
fi
|
||||
AC_CONFIG_COMMANDS_PRE(
|
||||
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
|
||||
AC_MSG_ERROR([[conditional "$1" was never defined.
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# AM_EXTRA_RECURSIVE_TARGETS -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_EXTRA_RECURSIVE_TARGETS
|
||||
# --------------------------
|
||||
# Define the list of user recursive targets. This macro exists only to
|
||||
# be traced by Automake, which will ensure that a proper definition of
|
||||
# user-defined recursive targets (and associated rules) is propagated
|
||||
# into all the generated Makefiles.
|
||||
# TODO: We should really reject non-literal arguments here...
|
||||
AC_DEFUN([AM_EXTRA_RECURSIVE_TARGETS], [])
|
||||
|
||||
# Do all the work for Automake. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This macro actually does too much. Some checks are only needed if
|
||||
# your package does certain things. But this isn't really a big deal.
|
||||
|
||||
dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
|
||||
m4_define([AC_PROG_CC],
|
||||
m4_defn([AC_PROG_CC])
|
||||
[_AM_PROG_CC_C_O
|
||||
])
|
||||
|
||||
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
|
||||
# AM_INIT_AUTOMAKE([OPTIONS])
|
||||
# -----------------------------------------------
|
||||
# The call with PACKAGE and VERSION arguments is the old style
|
||||
# call (pre autoconf-2.50), which is being phased out. PACKAGE
|
||||
# and VERSION should now be passed to AC_INIT and removed from
|
||||
# the call to AM_INIT_AUTOMAKE.
|
||||
# We support both call styles for the transition. After
|
||||
# the next Automake release, Autoconf can make the AC_INIT
|
||||
# arguments mandatory, and then we can depend on a new Autoconf
|
||||
# release and drop the old call support.
|
||||
AC_DEFUN([AM_INIT_AUTOMAKE],
|
||||
[AC_PREREQ([2.65])dnl
|
||||
m4_ifdef([_$0_ALREADY_INIT],
|
||||
[m4_fatal([$0 expanded multiple times
|
||||
]m4_defn([_$0_ALREADY_INIT]))],
|
||||
[m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
|
||||
dnl Autoconf wants to disallow AM_ names. We explicitly allow
|
||||
dnl the ones we care about.
|
||||
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
|
||||
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
|
||||
AC_REQUIRE([AC_PROG_INSTALL])dnl
|
||||
if test "`cd $srcdir && pwd`" != "`pwd`"; then
|
||||
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
|
||||
# is not polluted with repeated "-I."
|
||||
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
|
||||
# test to see if srcdir already configured
|
||||
if test -f $srcdir/config.status; then
|
||||
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
|
||||
fi
|
||||
fi
|
||||
|
||||
# test whether we have cygpath
|
||||
if test -z "$CYGPATH_W"; then
|
||||
if (cygpath --version) >/dev/null 2>/dev/null; then
|
||||
CYGPATH_W='cygpath -w'
|
||||
else
|
||||
CYGPATH_W=echo
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([CYGPATH_W])
|
||||
|
||||
# Define the identity of the package.
|
||||
dnl Distinguish between old-style and new-style calls.
|
||||
m4_ifval([$2],
|
||||
[AC_DIAGNOSE([obsolete],
|
||||
[$0: two- and three-arguments forms are deprecated.])
|
||||
m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
|
||||
AC_SUBST([PACKAGE], [$1])dnl
|
||||
AC_SUBST([VERSION], [$2])],
|
||||
[_AM_SET_OPTIONS([$1])dnl
|
||||
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
|
||||
m4_if(
|
||||
m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
|
||||
[ok:ok],,
|
||||
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
|
||||
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
|
||||
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
|
||||
|
||||
_AM_IF_OPTION([no-define],,
|
||||
[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
|
||||
AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
|
||||
|
||||
# Some tools Automake needs.
|
||||
AC_REQUIRE([AM_SANITY_CHECK])dnl
|
||||
AC_REQUIRE([AC_ARG_PROGRAM])dnl
|
||||
AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
|
||||
AM_MISSING_PROG([AUTOCONF], [autoconf])
|
||||
AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
|
||||
AM_MISSING_PROG([AUTOHEADER], [autoheader])
|
||||
AM_MISSING_PROG([MAKEINFO], [makeinfo])
|
||||
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
|
||||
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
|
||||
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
|
||||
# For better backward compatibility. To be removed once Automake 1.9.x
|
||||
# dies out for good. For more background, see:
|
||||
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
||||
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||
AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
|
||||
# We need awk for the "check" target (and possibly the TAP driver). The
|
||||
# system "awk" is bad on some platforms.
|
||||
AC_REQUIRE([AC_PROG_AWK])dnl
|
||||
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
||||
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
||||
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
|
||||
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
|
||||
[_AM_PROG_TAR([v7])])])
|
||||
_AM_IF_OPTION([no-dependencies],,
|
||||
[AC_PROVIDE_IFELSE([AC_PROG_CC],
|
||||
[_AM_DEPENDENCIES([CC])],
|
||||
[m4_define([AC_PROG_CC],
|
||||
m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_CXX],
|
||||
[_AM_DEPENDENCIES([CXX])],
|
||||
[m4_define([AC_PROG_CXX],
|
||||
m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
|
||||
[_AM_DEPENDENCIES([OBJC])],
|
||||
[m4_define([AC_PROG_OBJC],
|
||||
m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
|
||||
[_AM_DEPENDENCIES([OBJCXX])],
|
||||
[m4_define([AC_PROG_OBJCXX],
|
||||
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
|
||||
])
|
||||
# Variables for tags utilities; see am/tags.am
|
||||
if test -z "$CTAGS"; then
|
||||
CTAGS=ctags
|
||||
fi
|
||||
AC_SUBST([CTAGS])
|
||||
if test -z "$ETAGS"; then
|
||||
ETAGS=etags
|
||||
fi
|
||||
AC_SUBST([ETAGS])
|
||||
if test -z "$CSCOPE"; then
|
||||
CSCOPE=cscope
|
||||
fi
|
||||
AC_SUBST([CSCOPE])
|
||||
|
||||
AC_REQUIRE([_AM_SILENT_RULES])dnl
|
||||
dnl The testsuite driver may need to know about EXEEXT, so add the
|
||||
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
|
||||
dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
|
||||
AC_CONFIG_COMMANDS_PRE(dnl
|
||||
[m4_provide_if([_AM_COMPILER_EXEEXT],
|
||||
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
|
||||
|
||||
AC_REQUIRE([_AM_PROG_RM_F])
|
||||
AC_REQUIRE([_AM_PROG_XARGS_N])
|
||||
|
||||
dnl The trailing newline in this macro's definition is deliberate, for
|
||||
dnl backward compatibility and to allow trailing 'dnl'-style comments
|
||||
dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
|
||||
])
|
||||
|
||||
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
|
||||
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
|
||||
dnl mangled by Autoconf and run in a shell conditional statement.
|
||||
m4_define([_AC_COMPILER_EXEEXT],
|
||||
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
|
||||
|
||||
# When config.status generates a header, we must update the stamp-h file.
|
||||
# This file resides in the same directory as the config header
|
||||
# that is generated. The stamp files are numbered to have different names.
|
||||
|
||||
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
|
||||
# loop where config.status creates the headers, so we can generate
|
||||
# our stamp files there.
|
||||
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
|
||||
[# Compute $1's index in $config_headers.
|
||||
_am_arg=$1
|
||||
_am_stamp_count=1
|
||||
for _am_header in $config_headers :; do
|
||||
case $_am_header in
|
||||
$_am_arg | $_am_arg:* )
|
||||
break ;;
|
||||
* )
|
||||
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
|
||||
esac
|
||||
done
|
||||
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
|
||||
|
||||
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_PROG_INSTALL_SH
|
||||
# ------------------
|
||||
# Define $install_sh.
|
||||
AC_DEFUN([AM_PROG_INSTALL_SH],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
if test x"${install_sh+set}" != xset; then
|
||||
case $am_aux_dir in
|
||||
*\ * | *\ *)
|
||||
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
|
||||
*)
|
||||
install_sh="\${SHELL} $am_aux_dir/install-sh"
|
||||
esac
|
||||
fi
|
||||
AC_SUBST([install_sh])])
|
||||
|
||||
# Copyright (C) 2003-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# Check whether the underlying file-system supports filenames
|
||||
# with a leading dot. For instance MS-DOS doesn't.
|
||||
AC_DEFUN([AM_SET_LEADING_DOT],
|
||||
[rm -rf .tst 2>/dev/null
|
||||
mkdir .tst 2>/dev/null
|
||||
if test -d .tst; then
|
||||
am__leading_dot=.
|
||||
else
|
||||
am__leading_dot=_
|
||||
fi
|
||||
rmdir .tst 2>/dev/null
|
||||
AC_SUBST([am__leading_dot])])
|
||||
|
||||
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_MISSING_PROG(NAME, PROGRAM)
|
||||
# ------------------------------
|
||||
AC_DEFUN([AM_MISSING_PROG],
|
||||
[AC_REQUIRE([AM_MISSING_HAS_RUN])
|
||||
$1=${$1-"${am_missing_run}$2"}
|
||||
AC_SUBST($1)])
|
||||
|
||||
# AM_MISSING_HAS_RUN
|
||||
# ------------------
|
||||
# Define MISSING if not defined so far and test if it is modern enough.
|
||||
# If it is, set am_missing_run to use it, otherwise, to nothing.
|
||||
AC_DEFUN([AM_MISSING_HAS_RUN],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
AC_REQUIRE_AUX_FILE([missing])dnl
|
||||
if test x"${MISSING+set}" != xset; then
|
||||
MISSING="\${SHELL} '$am_aux_dir/missing'"
|
||||
fi
|
||||
# Use eval to expand $SHELL
|
||||
if eval "$MISSING --is-lightweight"; then
|
||||
am_missing_run="$MISSING "
|
||||
else
|
||||
am_missing_run=
|
||||
AC_MSG_WARN(['missing' script is too old or missing])
|
||||
fi
|
||||
])
|
||||
|
||||
# Helper functions for option handling. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_MANGLE_OPTION(NAME)
|
||||
# -----------------------
|
||||
AC_DEFUN([_AM_MANGLE_OPTION],
|
||||
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
|
||||
|
||||
# _AM_SET_OPTION(NAME)
|
||||
# --------------------
|
||||
# Set option NAME. Presently that only means defining a flag for this option.
|
||||
AC_DEFUN([_AM_SET_OPTION],
|
||||
[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
|
||||
|
||||
# _AM_SET_OPTIONS(OPTIONS)
|
||||
# ------------------------
|
||||
# OPTIONS is a space-separated list of Automake options.
|
||||
AC_DEFUN([_AM_SET_OPTIONS],
|
||||
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
|
||||
|
||||
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
|
||||
# -------------------------------------------
|
||||
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
|
||||
AC_DEFUN([_AM_IF_OPTION],
|
||||
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
|
||||
|
||||
# Copyright (C) 2022-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_PROG_RM_F
|
||||
# ---------------
|
||||
# Check whether 'rm -f' without any arguments works.
|
||||
# https://bugs.gnu.org/10828
|
||||
AC_DEFUN([_AM_PROG_RM_F],
|
||||
[am__rm_f_notfound=
|
||||
AS_IF([(rm -f && rm -fr && rm -rf) 2>/dev/null], [], [am__rm_f_notfound='""'])
|
||||
AC_SUBST(am__rm_f_notfound)
|
||||
])
|
||||
|
||||
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_RUN_LOG(COMMAND)
|
||||
# -------------------
|
||||
# Run COMMAND, save the exit status in ac_status, and log it.
|
||||
# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
|
||||
AC_DEFUN([AM_RUN_LOG],
|
||||
[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
|
||||
($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
|
||||
(exit $ac_status); }])
|
||||
|
||||
# Check to make sure that the build environment is sane. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_SLEEP_FRACTIONAL_SECONDS
|
||||
# ----------------------------
|
||||
AC_DEFUN([_AM_SLEEP_FRACTIONAL_SECONDS], [dnl
|
||||
AC_CACHE_CHECK([whether sleep supports fractional seconds],
|
||||
am_cv_sleep_fractional_seconds, [dnl
|
||||
AS_IF([sleep 0.001 2>/dev/null], [am_cv_sleep_fractional_seconds=yes],
|
||||
[am_cv_sleep_fractional_seconds=no])
|
||||
])])
|
||||
|
||||
# _AM_FILESYSTEM_TIMESTAMP_RESOLUTION
|
||||
# -----------------------------------
|
||||
# Determine the filesystem's resolution for file modification
|
||||
# timestamps. The coarsest we know of is FAT, with a resolution
|
||||
# of only two seconds, even with the most recent "exFAT" extensions.
|
||||
# The finest (e.g. ext4 with large inodes, XFS, ZFS) is one
|
||||
# nanosecond, matching clock_gettime. However, it is probably not
|
||||
# possible to delay execution of a shell script for less than one
|
||||
# millisecond, due to process creation overhead and scheduling
|
||||
# granularity, so we don't check for anything finer than that. (See below.)
|
||||
AC_DEFUN([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION], [dnl
|
||||
AC_REQUIRE([_AM_SLEEP_FRACTIONAL_SECONDS])
|
||||
AC_CACHE_CHECK([filesystem timestamp resolution],
|
||||
am_cv_filesystem_timestamp_resolution, [dnl
|
||||
# Default to the worst case.
|
||||
am_cv_filesystem_timestamp_resolution=2
|
||||
|
||||
# Only try to go finer than 1 sec if sleep can do it.
|
||||
# Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work,
|
||||
# - 1 sec is not much of a win compared to 2 sec, and
|
||||
# - it takes 2 seconds to perform the test whether 1 sec works.
|
||||
#
|
||||
# Instead, just use the default 2s on platforms that have 1s resolution,
|
||||
# accept the extra 1s delay when using $sleep in the Automake tests, in
|
||||
# exchange for not incurring the 2s delay for running the test for all
|
||||
# packages.
|
||||
#
|
||||
am_try_resolutions=
|
||||
if test "$am_cv_sleep_fractional_seconds" = yes; then
|
||||
# Even a millisecond often causes a bunch of false positives,
|
||||
# so just try a hundredth of a second. The time saved between .001 and
|
||||
# .01 is not terribly consequential.
|
||||
am_try_resolutions="0.01 0.1 $am_try_resolutions"
|
||||
fi
|
||||
|
||||
# In order to catch current-generation FAT out, we must *modify* files
|
||||
# that already exist; the *creation* timestamp is finer. Use names
|
||||
# that make ls -t sort them differently when they have equal
|
||||
# timestamps than when they have distinct timestamps, keeping
|
||||
# in mind that ls -t prints the *newest* file first.
|
||||
rm -f conftest.ts?
|
||||
: > conftest.ts1
|
||||
: > conftest.ts2
|
||||
: > conftest.ts3
|
||||
|
||||
# Make sure ls -t actually works. Do 'set' in a subshell so we don't
|
||||
# clobber the current shell's arguments. (Outer-level square brackets
|
||||
# are removed by m4; they're present so that m4 does not expand
|
||||
# <dollar><star>; be careful, easy to get confused.)
|
||||
if (
|
||||
set X `[ls -t conftest.ts[12]]` &&
|
||||
{
|
||||
test "$[]*" != "X conftest.ts1 conftest.ts2" ||
|
||||
test "$[]*" != "X conftest.ts2 conftest.ts1";
|
||||
}
|
||||
); then :; else
|
||||
# If neither matched, then we have a broken ls. This can happen
|
||||
# if, for instance, CONFIG_SHELL is bash and it inherits a
|
||||
# broken ls alias from the environment. This has actually
|
||||
# happened. Such a system could not be considered "sane".
|
||||
_AS_ECHO_UNQUOTED(
|
||||
["Bad output from ls -t: \"`[ls -t conftest.ts[12]]`\""],
|
||||
[AS_MESSAGE_LOG_FD])
|
||||
AC_MSG_FAILURE([ls -t produces unexpected output.
|
||||
Make sure there is not a broken ls alias in your environment.])
|
||||
fi
|
||||
|
||||
for am_try_res in $am_try_resolutions; do
|
||||
# Any one fine-grained sleep might happen to cross the boundary
|
||||
# between two values of a coarser actual resolution, but if we do
|
||||
# two fine-grained sleeps in a row, at least one of them will fall
|
||||
# entirely within a coarse interval.
|
||||
echo alpha > conftest.ts1
|
||||
sleep $am_try_res
|
||||
echo beta > conftest.ts2
|
||||
sleep $am_try_res
|
||||
echo gamma > conftest.ts3
|
||||
|
||||
# We assume that 'ls -t' will make use of high-resolution
|
||||
# timestamps if the operating system supports them at all.
|
||||
if (set X `ls -t conftest.ts?` &&
|
||||
test "$[]2" = conftest.ts3 &&
|
||||
test "$[]3" = conftest.ts2 &&
|
||||
test "$[]4" = conftest.ts1); then
|
||||
#
|
||||
# Ok, ls -t worked. If we're at a resolution of 1 second, we're done,
|
||||
# because we don't need to test make.
|
||||
make_ok=true
|
||||
if test $am_try_res != 1; then
|
||||
# But if we've succeeded so far with a subsecond resolution, we
|
||||
# have one more thing to check: make. It can happen that
|
||||
# everything else supports the subsecond mtimes, but make doesn't;
|
||||
# notably on macOS, which ships make 3.81 from 2006 (the last one
|
||||
# released under GPLv2). https://bugs.gnu.org/68808
|
||||
#
|
||||
# We test $MAKE if it is defined in the environment, else "make".
|
||||
# It might get overridden later, but our hope is that in practice
|
||||
# it does not matter: it is the system "make" which is (by far)
|
||||
# the most likely to be broken, whereas if the user overrides it,
|
||||
# probably they did so with a better, or at least not worse, make.
|
||||
# https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html
|
||||
#
|
||||
# Create a Makefile (real tab character here):
|
||||
rm -f conftest.mk
|
||||
echo 'conftest.ts1: conftest.ts2' >conftest.mk
|
||||
echo ' touch conftest.ts2' >>conftest.mk
|
||||
#
|
||||
# Now, running
|
||||
# touch conftest.ts1; touch conftest.ts2; make
|
||||
# should touch ts1 because ts2 is newer. This could happen by luck,
|
||||
# but most often, it will fail if make's support is insufficient. So
|
||||
# test for several consecutive successes.
|
||||
#
|
||||
# (We reuse conftest.ts[12] because we still want to modify existing
|
||||
# files, not create new ones, per above.)
|
||||
n=0
|
||||
make=${MAKE-make}
|
||||
until test $n -eq 3; do
|
||||
echo one > conftest.ts1
|
||||
sleep $am_try_res
|
||||
echo two > conftest.ts2 # ts2 should now be newer than ts1
|
||||
if $make -f conftest.mk | grep 'up to date' >/dev/null; then
|
||||
make_ok=false
|
||||
break # out of $n loop
|
||||
fi
|
||||
n=`expr $n + 1`
|
||||
done
|
||||
fi
|
||||
#
|
||||
if $make_ok; then
|
||||
# Everything we know to check worked out, so call this resolution good.
|
||||
am_cv_filesystem_timestamp_resolution=$am_try_res
|
||||
break # out of $am_try_res loop
|
||||
fi
|
||||
# Otherwise, we'll go on to check the next resolution.
|
||||
fi
|
||||
done
|
||||
rm -f conftest.ts?
|
||||
# (end _am_filesystem_timestamp_resolution)
|
||||
])])
|
||||
|
||||
# AM_SANITY_CHECK
|
||||
# ---------------
|
||||
AC_DEFUN([AM_SANITY_CHECK],
|
||||
[AC_REQUIRE([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION])
|
||||
# This check should not be cached, as it may vary across builds of
|
||||
# different projects.
|
||||
AC_MSG_CHECKING([whether build environment is sane])
|
||||
# Reject unsafe characters in $srcdir or the absolute working directory
|
||||
# name. Accept space and tab only in the latter.
|
||||
am_lf='
|
||||
'
|
||||
case `pwd` in
|
||||
*[[\\\"\#\$\&\'\`$am_lf]]*)
|
||||
AC_MSG_ERROR([unsafe absolute working directory name]);;
|
||||
esac
|
||||
case $srcdir in
|
||||
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
|
||||
AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
|
||||
esac
|
||||
|
||||
# Do 'set' in a subshell so we don't clobber the current shell's
|
||||
# arguments. Must try -L first in case configure is actually a
|
||||
# symlink; some systems play weird games with the mod time of symlinks
|
||||
# (eg FreeBSD returns the mod time of the symlink's containing
|
||||
# directory).
|
||||
am_build_env_is_sane=no
|
||||
am_has_slept=no
|
||||
rm -f conftest.file
|
||||
for am_try in 1 2; do
|
||||
echo "timestamp, slept: $am_has_slept" > conftest.file
|
||||
if (
|
||||
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
|
||||
if test "$[]*" = "X"; then
|
||||
# -L didn't work.
|
||||
set X `ls -t "$srcdir/configure" conftest.file`
|
||||
fi
|
||||
test "$[]2" = conftest.file
|
||||
); then
|
||||
am_build_env_is_sane=yes
|
||||
break
|
||||
fi
|
||||
# Just in case.
|
||||
sleep "$am_cv_filesystem_timestamp_resolution"
|
||||
am_has_slept=yes
|
||||
done
|
||||
|
||||
AC_MSG_RESULT([$am_build_env_is_sane])
|
||||
if test "$am_build_env_is_sane" = no; then
|
||||
AC_MSG_ERROR([newly created file is older than distributed files!
|
||||
Check your system clock])
|
||||
fi
|
||||
|
||||
# If we didn't sleep, we still need to ensure time stamps of config.status and
|
||||
# generated files are strictly newer.
|
||||
am_sleep_pid=
|
||||
AS_IF([test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1],, [dnl
|
||||
( sleep "$am_cv_filesystem_timestamp_resolution" ) &
|
||||
am_sleep_pid=$!
|
||||
])
|
||||
AC_CONFIG_COMMANDS_PRE(
|
||||
[AC_MSG_CHECKING([that generated files are newer than configure])
|
||||
if test -n "$am_sleep_pid"; then
|
||||
# Hide warnings about reused PIDs.
|
||||
wait $am_sleep_pid 2>/dev/null
|
||||
fi
|
||||
AC_MSG_RESULT([done])])
|
||||
rm -f conftest.file
|
||||
])
|
||||
|
||||
# Copyright (C) 2009-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_SILENT_RULES
|
||||
# ----------------
|
||||
# Enable less verbose build rules support.
|
||||
AC_DEFUN([_AM_SILENT_RULES],
|
||||
[AM_DEFAULT_VERBOSITY=1
|
||||
AC_ARG_ENABLE([silent-rules], [dnl
|
||||
AS_HELP_STRING(
|
||||
[--enable-silent-rules],
|
||||
[less verbose build output (undo: "make V=1")])
|
||||
AS_HELP_STRING(
|
||||
[--disable-silent-rules],
|
||||
[verbose build output (undo: "make V=0")])dnl
|
||||
])
|
||||
dnl
|
||||
dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
|
||||
dnl do not support nested variable expansions.
|
||||
dnl See automake bug#9928 and bug#10237.
|
||||
am_make=${MAKE-make}
|
||||
AC_CACHE_CHECK([whether $am_make supports nested variables],
|
||||
[am_cv_make_support_nested_variables],
|
||||
[if AS_ECHO([['TRUE=$(BAR$(V))
|
||||
BAR0=false
|
||||
BAR1=true
|
||||
V=1
|
||||
am__doit:
|
||||
@$(TRUE)
|
||||
.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
|
||||
am_cv_make_support_nested_variables=yes
|
||||
else
|
||||
am_cv_make_support_nested_variables=no
|
||||
fi])
|
||||
AC_SUBST([AM_V])dnl
|
||||
AM_SUBST_NOTMAKE([AM_V])dnl
|
||||
AC_SUBST([AM_DEFAULT_V])dnl
|
||||
AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
|
||||
AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
|
||||
AM_BACKSLASH='\'
|
||||
AC_SUBST([AM_BACKSLASH])dnl
|
||||
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
|
||||
dnl Delay evaluation of AM_DEFAULT_VERBOSITY to the end to allow multiple calls
|
||||
dnl to AM_SILENT_RULES to change the default value.
|
||||
AC_CONFIG_COMMANDS_PRE([dnl
|
||||
case $enable_silent_rules in @%:@ (((
|
||||
yes) AM_DEFAULT_VERBOSITY=0;;
|
||||
no) AM_DEFAULT_VERBOSITY=1;;
|
||||
esac
|
||||
if test $am_cv_make_support_nested_variables = yes; then
|
||||
dnl Using '$V' instead of '$(V)' breaks IRIX make.
|
||||
AM_V='$(V)'
|
||||
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
|
||||
else
|
||||
AM_V=$AM_DEFAULT_VERBOSITY
|
||||
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
|
||||
fi
|
||||
])dnl
|
||||
])
|
||||
|
||||
# AM_SILENT_RULES([DEFAULT])
|
||||
# --------------------------
|
||||
# Set the default verbosity level to DEFAULT ("yes" being less verbose, "no" or
|
||||
# empty being verbose).
|
||||
AC_DEFUN([AM_SILENT_RULES],
|
||||
[AC_REQUIRE([_AM_SILENT_RULES])
|
||||
AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1])])
|
||||
|
||||
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_PROG_INSTALL_STRIP
|
||||
# ---------------------
|
||||
# One issue with vendor 'install' (even GNU) is that you can't
|
||||
# specify the program used to strip binaries. This is especially
|
||||
# annoying in cross-compiling environments, where the build's strip
|
||||
# is unlikely to handle the host's binaries.
|
||||
# Fortunately install-sh will honor a STRIPPROG variable, so we
|
||||
# always use install-sh in "make install-strip", and initialize
|
||||
# STRIPPROG with the value of the STRIP variable (set by the user).
|
||||
AC_DEFUN([AM_PROG_INSTALL_STRIP],
|
||||
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
|
||||
# Installed binaries are usually stripped using 'strip' when the user
|
||||
# run "make install-strip". However 'strip' might not be the right
|
||||
# tool to use in cross-compilation environments, therefore Automake
|
||||
# will honor the 'STRIP' environment variable to overrule this program.
|
||||
dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
|
||||
if test "$cross_compiling" != no; then
|
||||
AC_CHECK_TOOL([STRIP], [strip], :)
|
||||
fi
|
||||
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
|
||||
AC_SUBST([INSTALL_STRIP_PROGRAM])])
|
||||
|
||||
# Copyright (C) 2006-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# ---------------------------
|
||||
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
|
||||
# This macro is traced by Automake.
|
||||
AC_DEFUN([_AM_SUBST_NOTMAKE])
|
||||
|
||||
# AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# --------------------------
|
||||
# Public sister of _AM_SUBST_NOTMAKE.
|
||||
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
|
||||
|
||||
# Check how to create a tarball. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2004-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_PROG_TAR(FORMAT)
|
||||
# --------------------
|
||||
# Check how to create a tarball in format FORMAT.
|
||||
# FORMAT should be one of 'v7', 'ustar', or 'pax'.
|
||||
#
|
||||
# Substitute a variable $(am__tar) that is a command
|
||||
# writing to stdout a FORMAT-tarball containing the directory
|
||||
# $tardir.
|
||||
# tardir=directory && $(am__tar) > result.tar
|
||||
#
|
||||
# Substitute a variable $(am__untar) that extract such
|
||||
# a tarball read from stdin.
|
||||
# $(am__untar) < result.tar
|
||||
#
|
||||
AC_DEFUN([_AM_PROG_TAR],
|
||||
[# Always define AMTAR for backward compatibility. Yes, it's still used
|
||||
# in the wild :-( We should find a proper way to deprecate it ...
|
||||
AC_SUBST([AMTAR], ['$${TAR-tar}'])
|
||||
|
||||
# We'll loop over all known methods to create a tar archive until one works.
|
||||
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
|
||||
|
||||
m4_if([$1], [v7],
|
||||
[am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
|
||||
|
||||
[m4_case([$1],
|
||||
[ustar],
|
||||
[# The POSIX 1988 'ustar' format is defined with fixed-size fields.
|
||||
# There is notably a 21 bits limit for the UID and the GID. In fact,
|
||||
# the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
|
||||
# and bug#13588).
|
||||
am_max_uid=2097151 # 2^21 - 1
|
||||
am_max_gid=$am_max_uid
|
||||
# The $UID and $GID variables are not portable, so we need to resort
|
||||
# to the POSIX-mandated id(1) utility. Errors in the 'id' calls
|
||||
# below are definitely unexpected, so allow the users to see them
|
||||
# (that is, avoid stderr redirection).
|
||||
am_uid=`id -u || echo unknown`
|
||||
am_gid=`id -g || echo unknown`
|
||||
AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
|
||||
if test x$am_uid = xunknown; then
|
||||
AC_MSG_WARN([ancient id detected; assuming current UID is ok, but dist-ustar might not work])
|
||||
elif test $am_uid -le $am_max_uid; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
_am_tools=none
|
||||
fi
|
||||
AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
|
||||
if test x$gm_gid = xunknown; then
|
||||
AC_MSG_WARN([ancient id detected; assuming current GID is ok, but dist-ustar might not work])
|
||||
elif test $am_gid -le $am_max_gid; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
_am_tools=none
|
||||
fi],
|
||||
|
||||
[pax],
|
||||
[],
|
||||
|
||||
[m4_fatal([Unknown tar format])])
|
||||
|
||||
AC_MSG_CHECKING([how to create a $1 tar archive])
|
||||
|
||||
# Go ahead even if we have the value already cached. We do so because we
|
||||
# need to set the values for the 'am__tar' and 'am__untar' variables.
|
||||
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
|
||||
|
||||
for _am_tool in $_am_tools; do
|
||||
case $_am_tool in
|
||||
gnutar)
|
||||
for _am_tar in tar gnutar gtar; do
|
||||
AM_RUN_LOG([$_am_tar --version]) && break
|
||||
done
|
||||
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
|
||||
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
|
||||
am__untar="$_am_tar -xf -"
|
||||
;;
|
||||
plaintar)
|
||||
# Must skip GNU tar: if it does not support --format= it doesn't create
|
||||
# ustar tarball either.
|
||||
(tar --version) >/dev/null 2>&1 && continue
|
||||
am__tar='tar chf - "$$tardir"'
|
||||
am__tar_='tar chf - "$tardir"'
|
||||
am__untar='tar xf -'
|
||||
;;
|
||||
pax)
|
||||
am__tar='pax -L -x $1 -w "$$tardir"'
|
||||
am__tar_='pax -L -x $1 -w "$tardir"'
|
||||
am__untar='pax -r'
|
||||
;;
|
||||
cpio)
|
||||
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
|
||||
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
|
||||
am__untar='cpio -i -H $1 -d'
|
||||
;;
|
||||
none)
|
||||
am__tar=false
|
||||
am__tar_=false
|
||||
am__untar=false
|
||||
;;
|
||||
esac
|
||||
|
||||
# If the value was cached, stop now. We just wanted to have am__tar
|
||||
# and am__untar set.
|
||||
test -n "${am_cv_prog_tar_$1}" && break
|
||||
|
||||
# tar/untar a dummy directory, and stop if the command works.
|
||||
rm -rf conftest.dir
|
||||
mkdir conftest.dir
|
||||
echo GrepMe > conftest.dir/file
|
||||
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
|
||||
rm -rf conftest.dir
|
||||
if test -s conftest.tar; then
|
||||
AM_RUN_LOG([$am__untar <conftest.tar])
|
||||
AM_RUN_LOG([cat conftest.dir/file])
|
||||
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
|
||||
fi
|
||||
done
|
||||
rm -rf conftest.dir
|
||||
|
||||
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
|
||||
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
|
||||
|
||||
AC_SUBST([am__tar])
|
||||
AC_SUBST([am__untar])
|
||||
]) # _AM_PROG_TAR
|
||||
|
||||
# Copyright (C) 2022-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_PROG_XARGS_N
|
||||
# ----------------
|
||||
# Check whether 'xargs -n' works. It should work everywhere, so the fallback
|
||||
# is not optimized at all as we never expect to use it.
|
||||
AC_DEFUN([_AM_PROG_XARGS_N],
|
||||
[AC_CACHE_CHECK([xargs -n works], am_cv_xargs_n_works, [dnl
|
||||
AS_IF([test "`echo 1 2 3 | xargs -n2 echo`" = "1 2
|
||||
3"], [am_cv_xargs_n_works=yes], [am_cv_xargs_n_works=no])])
|
||||
AS_IF([test "$am_cv_xargs_n_works" = yes], [am__xargs_n='xargs -n'], [dnl
|
||||
am__xargs_n='am__xargs_n () { shift; sed "s/ /\\n/g" | while read am__xargs_n_arg; do "$@" "$am__xargs_n_arg"; done; }'
|
||||
])dnl
|
||||
AC_SUBST(am__xargs_n)
|
||||
])
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"mproxy/pkg/auxx509"
|
||||
|
||||
yaml "go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
Address string `json:"address" yaml:"address"`
|
||||
Port uint32 `json:"port" yaml:"port"`
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
Basepath string `json:"basepath" yaml:"basepath"`
|
||||
}
|
||||
|
||||
type Storage struct {
|
||||
Basepath string `json:"basepath" yaml:"basepath"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Service Service `json:"service" yaml:"service"`
|
||||
Database Database `json:"database" yaml:"database"`
|
||||
Storage Storage `json:"storage" yaml:"storage"`
|
||||
AsDaemon bool `json:"asDaemon" yaml:"asDaemon"`
|
||||
Logpath string `json:"logpath" yaml:"logpath"`
|
||||
Runpath string `json:"runpath" yaml:"runpath"`
|
||||
Version string `json:"version" yaml:"version"`
|
||||
Certpath string `json:"certpath,omitempty" yaml:"certpath,omitempty"`
|
||||
Keypath string `json:"keypath,omitempty" yaml:"keypath,omitempty"`
|
||||
X509Cert string `json:"-" yaml:"-"`
|
||||
X509Key string `json:"-" yaml:"-"`
|
||||
Datadir string `json:"datadir" yaml:"datadir"`
|
||||
Hostname string `json:"hostname" yaml:"hostname"`
|
||||
Hostnames []string `json:"hostnames" yaml:"hostnames"`
|
||||
LogLimit int64 `json:"logLimit" yaml:"logLimit"`
|
||||
RunUser string `json:"runUser" yaml:"runUser"`
|
||||
}
|
||||
|
||||
func NewConfig() *Config {
|
||||
logfile := fmt.Sprintf("%s.log", srvname)
|
||||
logpath := filepath.Join(logdir, logfile)
|
||||
|
||||
runfile := fmt.Sprintf("%s.pid", srvname)
|
||||
runpath := filepath.Join(rundir, runfile)
|
||||
|
||||
//certpath := fmt.Sprintf("%s.crt", srvname)
|
||||
//certpath = filepath.Join(confdir, certpath)
|
||||
|
||||
//keypath := fmt.Sprintf("%s.crt", srvname)
|
||||
//keypath = filepath.Join(confdir, keypath)
|
||||
|
||||
return &Config{
|
||||
Service: Service{
|
||||
Address: "0.0.0.0",
|
||||
Port: 1025,
|
||||
},
|
||||
Database: Database{
|
||||
Basepath: datadir,
|
||||
},
|
||||
Storage: Storage{
|
||||
Basepath: datadir,
|
||||
},
|
||||
AsDaemon: false,
|
||||
Logpath: logpath,
|
||||
Runpath: runpath,
|
||||
Version: version,
|
||||
Datadir: datadir,
|
||||
//Certpath: certpath,
|
||||
//Keypath: keypath,
|
||||
Hostnames: make([]string, 0),
|
||||
LogLimit: 1024 * 1024 * 10, // 10 Mb
|
||||
RunUser: "daemon",
|
||||
}
|
||||
}
|
||||
|
||||
func (conf *Config) String() string {
|
||||
confbytes, _ := yaml.Marshal(conf)
|
||||
return string(confbytes)
|
||||
}
|
||||
|
||||
func (conf *Config) ReadConfigfile() error {
|
||||
conffile := fmt.Sprintf("%s.yaml", srvname)
|
||||
confpath := filepath.Join(confdir, conffile)
|
||||
|
||||
confdata, err := ioutil.ReadFile(confpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = yaml.Unmarshal(confdata, conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (conf *Config) ReadX509Cert() error {
|
||||
var err error
|
||||
if conf.Certpath != "" && conf.Keypath != "" {
|
||||
if !filepath.IsAbs(conf.Certpath) {
|
||||
conf.Certpath = filepath.Join(confdir, conf.Certpath)
|
||||
}
|
||||
certBytes, err := os.ReadFile(conf.Certpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !filepath.IsAbs(conf.Keypath) {
|
||||
conf.Keypath = filepath.Join(confdir, conf.Keypath)
|
||||
}
|
||||
keyBytes, err := os.ReadFile(conf.Keypath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.X509Cert = string(certBytes)
|
||||
conf.X509Key = string(keyBytes)
|
||||
return err
|
||||
}
|
||||
/*
|
||||
if conf.X509Cert != "" && conf.X509Key != "" {
|
||||
x509Cert, err := base64.StdEncoding.DecodeString(conf.X509Cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.X509Cert = string(x509Cert)
|
||||
x509Key, err := base64.StdEncoding.DecodeString(conf.X509Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.X509Key = string(x509Key)
|
||||
}
|
||||
*/
|
||||
if conf.X509Cert == "" || conf.X509Key == "" {
|
||||
if conf.Hostname == "" {
|
||||
conf.Hostname, err = os.Hostname()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
certBytes, keyBytes, err := auxx509.CreateSelfSignedCert(conf.Hostname, conf.Hostnames...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.X509Cert = string(certBytes)
|
||||
conf.X509Key = string(keyBytes)
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package config
|
||||
|
||||
const (
|
||||
confdir = "@srv_confdir@"
|
||||
rundir = "@srv_rundir@"
|
||||
logdir = "@srv_logdir@"
|
||||
datadir = "@srv_datadir@"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
srvname = "@PACKAGE_NAME@d"
|
||||
)
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"mproxy/app/router"
|
||||
"mproxy/pkg/auxhttp"
|
||||
)
|
||||
|
||||
const (
|
||||
authTag = "authpass"
|
||||
userTag = "accountID"
|
||||
)
|
||||
|
||||
func (hand *Handler) AuthMiddleware(next router.Handler) router.Handler {
|
||||
var handlerFunc router.HandlerFunc
|
||||
|
||||
handlerFunc = func(rctx *router.Context) {
|
||||
success, err := hand.CheckAccess(rctx)
|
||||
if success {
|
||||
rctx.SetBool(authTag, true)
|
||||
}
|
||||
if err != nil {
|
||||
hand.logg.Errorf("Authorization middleware error: %v", err)
|
||||
}
|
||||
next.ServeHTTP(rctx)
|
||||
}
|
||||
return handlerFunc
|
||||
}
|
||||
|
||||
// Authentification
|
||||
func (hand *Handler) CheckAccess(rctx *router.Context) (bool, error) {
|
||||
var err error
|
||||
var success bool
|
||||
var username string
|
||||
var password string
|
||||
|
||||
authHeader := rctx.GetHeader("Proxy-Authorization")
|
||||
hand.logg.Debugf("Proxy-Authorization: [%s]", authHeader)
|
||||
if authHeader != "" {
|
||||
username, password, err = auxhttp.ParseBasicAuth(authHeader)
|
||||
if err != nil {
|
||||
return success, err
|
||||
}
|
||||
success, err := hand.ValidatePassword(rctx.Ctx, username, password)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !success {
|
||||
err = fmt.Errorf("Incorrect username or password")
|
||||
return false, err
|
||||
}
|
||||
return success, err
|
||||
}
|
||||
return success, err
|
||||
}
|
||||
|
||||
func (hand *Handler) ValidatePassword(ctx context.Context, username, password string) (bool, error) {
|
||||
var err error
|
||||
valid := true
|
||||
return valid, err
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"mproxy/app/proxoper"
|
||||
"mproxy/app/router"
|
||||
)
|
||||
|
||||
func (hand *Handler) ConnectTo(rctx *router.Context) {
|
||||
hostaddr, _ := rctx.GetSubpath("hostaddr")
|
||||
params := &proxoper.ConnectToParams{
|
||||
Hostaddr: hostaddr,
|
||||
}
|
||||
ctx := rctx.GetContext()
|
||||
_, err := hand.prop.ConnectTo(ctx, params)
|
||||
if err != nil {
|
||||
hand.logg.Errorf("ConnectTo error: %v", err)
|
||||
rctx.SetStatus(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
rctx.SetStatus(http.StatusOK)
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package handler
|
||||
|
||||
import (
|
||||
"mproxy/app/logger"
|
||||
"mproxy/app/router"
|
||||
|
||||
"mproxy/app/proxoper"
|
||||
"mproxy/app/servoper"
|
||||
|
||||
yaml "go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
type HandlerParams struct {
|
||||
ServOper *servoper.Operator
|
||||
ProxOper *proxoper.Operator
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
logg *logger.Logger
|
||||
seop *servoper.Operator
|
||||
prop *proxoper.Operator
|
||||
}
|
||||
|
||||
func NewHandler(params *HandlerParams) (*Handler, error) {
|
||||
var err error
|
||||
hand := &Handler{
|
||||
seop: params.ServOper,
|
||||
prop: params.ProxOper,
|
||||
}
|
||||
hand.logg = logger.NewLoggerWithSubject("handler")
|
||||
return hand, err
|
||||
}
|
||||
|
||||
func (hand *Handler) DumpHeaders(label string, rctx *router.Context) {
|
||||
headers := rctx.GetHeaders()
|
||||
yamlData, _ := yaml.Marshal(headers)
|
||||
hand.logg.Debugf("%s:\n%s\n", label, string(yamlData))
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"mproxy/app/router"
|
||||
)
|
||||
|
||||
func (hand *Handler) NotFound(rctx *router.Context) {
|
||||
hand.logg.Warningf("Route for [%s %s] not found", rctx.Request.Method, rctx.Request.URL.String())
|
||||
rctx.SetStatus(http.StatusNotFound)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"mproxy/app/router"
|
||||
)
|
||||
|
||||
type Response[T any] struct {
|
||||
Error bool `json:"error" yaml:"error"`
|
||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||
Result T `json:"result,omitempty" yaml:"result,result"`
|
||||
}
|
||||
|
||||
func NewResponse[T any]() *Response[T] {
|
||||
return &Response[T]{}
|
||||
}
|
||||
|
||||
func (hand *Handler) SendResult(rctx *router.Context, result any) {
|
||||
response := &Response[any]{
|
||||
Error: false,
|
||||
Result: result,
|
||||
}
|
||||
rctx.SendJSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
func (hand *Handler) SendError(rctx *router.Context, err error) {
|
||||
response := &Response[any]{
|
||||
Error: true,
|
||||
Message: err.Error(),
|
||||
}
|
||||
rctx.SendJSON(http.StatusOK, response)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package handler
|
||||
|
||||
import (
|
||||
"mproxy/app/router"
|
||||
"mproxy/app/servoper"
|
||||
)
|
||||
|
||||
func (hand *Handler) SendHello(rctx *router.Context) {
|
||||
params := &servoper.SendHelloParams{}
|
||||
res, _ := hand.seop.SendHello(params)
|
||||
hand.SendResult(rctx, res)
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package logger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
mtx sync.Mutex
|
||||
output io.WriteCloser = os.Stderr
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
subject string
|
||||
writer io.WriteCloser
|
||||
mtx *sync.Mutex
|
||||
}
|
||||
|
||||
func NewLoggerWithSubject(subj string) *Logger {
|
||||
return &Logger{
|
||||
subject: subj,
|
||||
writer: output,
|
||||
mtx: &mtx,
|
||||
}
|
||||
}
|
||||
|
||||
func NewLogger() *Logger {
|
||||
return &Logger{
|
||||
writer: output,
|
||||
mtx: &mtx,
|
||||
}
|
||||
}
|
||||
|
||||
func SetWriter(newOut io.WriteCloser) {
|
||||
mtx.Lock()
|
||||
output = newOut
|
||||
mtx.Unlock()
|
||||
}
|
||||
|
||||
func (logg *Logger) SetWriter(newOut io.WriteCloser) {
|
||||
mtx.Lock()
|
||||
logg.writer = newOut
|
||||
var newMtx sync.Mutex
|
||||
logg.mtx = &newMtx
|
||||
mtx.Unlock()
|
||||
}
|
||||
|
||||
func (logg *Logger) Debugf(message string, args ...any) {
|
||||
logg.printf("debug", message, args...)
|
||||
}
|
||||
|
||||
func (logg *Logger) Infof(message string, args ...any) {
|
||||
logg.printf("info", message, args...)
|
||||
}
|
||||
|
||||
func (logg *Logger) Warningf(message string, args ...any) {
|
||||
logg.printf("warning", message, args...)
|
||||
}
|
||||
|
||||
func (logg *Logger) Errorf(message string, args ...any) {
|
||||
logg.printf("error", message, args...)
|
||||
}
|
||||
|
||||
func (logg *Logger) printf(level, message string, args ...any) {
|
||||
timestamp := time.Now().Format(time.RFC3339)
|
||||
buffer := bytes.NewBuffer([]byte{})
|
||||
if logg.subject != "" {
|
||||
fmt.Fprintf(buffer, "%s %s.%s: ", timestamp, logg.subject, level)
|
||||
} else {
|
||||
fmt.Fprintf(buffer, "%s %s: ", timestamp, level)
|
||||
}
|
||||
fmt.Fprintf(buffer, message, args...)
|
||||
fmt.Fprintf(buffer, "\n")
|
||||
logg.mtx.Lock()
|
||||
fmt.Fprint(output, buffer.String())
|
||||
logg.mtx.Unlock()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package logger
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLogger(t *testing.T) {
|
||||
logg := NewLogger("test")
|
||||
logg.Debugf("foo: %s", "bar")
|
||||
}
|
||||
|
||||
func BenchmarkLoggerL(b *testing.B) {
|
||||
SetWriter(ioutil.Discard)
|
||||
logg := NewLogger("test")
|
||||
for i := 0; i < b.N; i++ {
|
||||
logg.Debugf("foo: %s", "bar")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLoggerP(b *testing.B) {
|
||||
SetWriter(ioutil.Discard)
|
||||
logg := NewLogger("test")
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
logg.Debugf("foo: %s", "bar")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package proxoper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ConnectToParams struct {
|
||||
Hostaddr string
|
||||
}
|
||||
|
||||
type ConnectToResult struct {
|
||||
Stream io.Writer
|
||||
}
|
||||
|
||||
func (oper *Operator) ConnectTo(ctx context.Context, param *ConnectToParams) (*ConnectToResult, error) {
|
||||
var err error
|
||||
res := &ConnectToResult{}
|
||||
return res, err
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package proxoper
|
||||
|
||||
import (
|
||||
"mproxy/app/logger"
|
||||
)
|
||||
|
||||
type OperatorParams struct{}
|
||||
|
||||
type Operator struct {
|
||||
logg *logger.Logger
|
||||
}
|
||||
|
||||
func NewOperator(params *OperatorParams) (*Operator, error) {
|
||||
var err error
|
||||
oper := &Operator{}
|
||||
oper.logg = logger.NewLoggerWithSubject("proxoper")
|
||||
return oper, err
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// The code reflect string-string map to taged structure
|
||||
// Limited, used only base types
|
||||
// Don't ask me how it works. I'm only writer ;)
|
||||
|
||||
func bindObj(obj interface{}, kvmap map[string]string, sTag string) error {
|
||||
var err error
|
||||
vElem := reflect.ValueOf(obj).Elem()
|
||||
sElem := reflect.TypeOf(obj).Elem()
|
||||
for i := 0; i < vElem.NumField(); i++ {
|
||||
vField := vElem.Field(i)
|
||||
tag := sElem.Field(i).Tag.Get(sTag)
|
||||
if tag != "" {
|
||||
sVal, exists := kvmap[tag]
|
||||
if exists {
|
||||
switch vField.Kind() {
|
||||
case reflect.String:
|
||||
vField.SetString(sVal)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
iVal, err := strconv.ParseInt(sVal, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vField.SetInt(iVal)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
iVal, err := strconv.ParseUint(sVal, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vField.SetUint(iVal)
|
||||
case reflect.Bool:
|
||||
bVal, err := strconv.ParseBool(sVal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vField.SetBool(bVal)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
fVal, err := strconv.ParseFloat(sVal, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vField.SetFloat(fVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
Ctx context.Context
|
||||
Request *http.Request
|
||||
Writer http.ResponseWriter
|
||||
PathMap map[string]string
|
||||
Bools map[string]bool
|
||||
Strings map[string]string
|
||||
StatusCode int
|
||||
}
|
||||
|
||||
func NewContext(writer http.ResponseWriter, request *http.Request) *Context {
|
||||
rctx := &Context{
|
||||
Writer: writer,
|
||||
Request: request,
|
||||
Ctx: request.Context(),
|
||||
PathMap: make(map[string]string),
|
||||
Bools: make(map[string]bool),
|
||||
Strings: make(map[string]string),
|
||||
}
|
||||
return rctx
|
||||
}
|
||||
|
||||
// Aux maps
|
||||
func (rctx *Context) SetBool(key string, value bool) {
|
||||
rctx.Bools[key] = value
|
||||
}
|
||||
|
||||
func (rctx *Context) GetBool(key string) (bool, bool) {
|
||||
exists, value := rctx.Bools[key]
|
||||
return exists, value
|
||||
}
|
||||
|
||||
func (rctx *Context) SetString(key string, value string) {
|
||||
rctx.Strings[key] = value
|
||||
}
|
||||
|
||||
func (rctx *Context) GetString(key string) (string, bool) {
|
||||
value, exists := rctx.Strings[key]
|
||||
return value, exists
|
||||
}
|
||||
|
||||
// Request
|
||||
func (rctx *Context) GetSubpath(key string) (string, bool) {
|
||||
value, exists := rctx.PathMap[key]
|
||||
return value, exists
|
||||
}
|
||||
|
||||
func (rctx *Context) URL() *url.URL {
|
||||
return rctx.Request.URL
|
||||
}
|
||||
|
||||
func (rctx *Context) GetQuery(key string) string {
|
||||
return rctx.Request.URL.Query().Get(key)
|
||||
}
|
||||
|
||||
func (rctx *Context) GetHeader(key string) string {
|
||||
return rctx.Request.Header.Get(key)
|
||||
}
|
||||
|
||||
func (rctx *Context) GetHeaders() http.Header {
|
||||
return rctx.Request.Header
|
||||
}
|
||||
|
||||
func (rctx *Context) GetContext() context.Context {
|
||||
return rctx.Request.Context()
|
||||
}
|
||||
|
||||
// Binding
|
||||
const emptyJSON = "{}"
|
||||
|
||||
func (rctx *Context) BindJSON(obj any) error {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
_, err := io.Copy(buffer, rctx.Request.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reqBody := buffer.Bytes()
|
||||
if len(reqBody) == 0 {
|
||||
reqBody = []byte(emptyJSON)
|
||||
}
|
||||
err = json.Unmarshal(reqBody, obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (rctx *Context) BindQuery(obj any) error {
|
||||
qMap := make(map[string]string)
|
||||
for key, val := range rctx.Request.URL.Query() {
|
||||
if len(val) == 1 {
|
||||
qMap[key] = val[0]
|
||||
}
|
||||
}
|
||||
return bindObj(obj, qMap, "param")
|
||||
}
|
||||
|
||||
// Response
|
||||
func (rctx *Context) SetHeader(key, value string) {
|
||||
rctx.Writer.Header().Set(key, value)
|
||||
}
|
||||
|
||||
func (rctx *Context) SetStatus(httpStatus int) {
|
||||
rctx.StatusCode = httpStatus
|
||||
rctx.Writer.WriteHeader(httpStatus)
|
||||
}
|
||||
|
||||
func (rctx *Context) SendJSON(statusCode int, payload any) {
|
||||
rctx.StatusCode = statusCode
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
json.NewEncoder(buffer).Encode(payload)
|
||||
rctx.Writer.Header().Set("Content-Type", "application/json")
|
||||
size := strconv.FormatInt(int64(len(buffer.Bytes())), 10)
|
||||
rctx.Writer.Header().Set("Content-Length", size)
|
||||
rctx.Writer.WriteHeader(statusCode)
|
||||
rctx.Writer.Write(buffer.Bytes())
|
||||
}
|
||||
|
||||
func (rctx *Context) SendText(statusCode int, payload string) {
|
||||
rctx.StatusCode = statusCode
|
||||
size := strconv.FormatInt(int64(len(payload)), 10)
|
||||
rctx.Writer.Header().Set("Content-Type", "text/plain")
|
||||
rctx.Writer.Header().Set("Content-Length", size)
|
||||
rctx.Writer.WriteHeader(statusCode)
|
||||
rctx.Writer.Write([]byte(payload))
|
||||
}
|
||||
|
||||
func (rctx *Context) SendBytes(statusCode int, ctype string, payload []byte) {
|
||||
rctx.StatusCode = statusCode
|
||||
size := strconv.FormatInt(int64(len(payload)), 10)
|
||||
rctx.Writer.Header().Set("Content-Type", ctype)
|
||||
rctx.Writer.Header().Set("Content-Length", size)
|
||||
rctx.Writer.WriteHeader(statusCode)
|
||||
rctx.Writer.Write(payload)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
func NewCorsMiddleware() MiddlewareFunc {
|
||||
mw := func(next Handler) Handler {
|
||||
return newCorsHandler(next)
|
||||
}
|
||||
return mw
|
||||
}
|
||||
|
||||
type corsHandler struct {
|
||||
next Handler
|
||||
}
|
||||
|
||||
func newCorsHandler(next Handler) *corsHandler {
|
||||
return &corsHandler{
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
|
||||
func (hand corsHandler) ServeHTTP(ctx *Context) {
|
||||
origin := ctx.Request.Header.Get("Origin")
|
||||
if origin != "" {
|
||||
ctx.SetHeader("Access-Control-Allow-Origin", origin)
|
||||
ctx.SetHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE, PATCH")
|
||||
ctx.SetHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
|
||||
ctx.SetHeader("Access-Control-Max-Age", "86400")
|
||||
ctx.SetHeader("Access-Control-Allow-Credentials", "true")
|
||||
}
|
||||
if ctx.Request.Method == "OPTIONS" {
|
||||
return
|
||||
}
|
||||
hand.next.ServeHTTP(ctx)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
func NewLoggingMiddleware(print func(string, ...any)) MiddlewareFunc {
|
||||
mw := func(next Handler) Handler {
|
||||
return newLoggingHandler(next, print)
|
||||
}
|
||||
return mw
|
||||
}
|
||||
|
||||
type loggingHandler struct {
|
||||
next Handler
|
||||
printFunc func(string, ...any)
|
||||
}
|
||||
|
||||
func newLoggingHandler(next Handler, print func(string, ...any)) *loggingHandler {
|
||||
return &loggingHandler{
|
||||
next: next,
|
||||
printFunc: print,
|
||||
}
|
||||
}
|
||||
|
||||
func (logging loggingHandler) ServeHTTP(rctx *Context) {
|
||||
logging.next.ServeHTTP(rctx)
|
||||
cl := rctx.Writer.Header().Get("Content-Length")
|
||||
logging.printFunc("%s %s %s %s %s %d", rctx.Request.RemoteAddr,
|
||||
rctx.Request.Method, rctx.Request.URL.String(),
|
||||
rctx.Request.Proto, cl, rctx.StatusCode)
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
compContextPlain int = iota
|
||||
compContextRegex
|
||||
|
||||
startRegex byte = '{'
|
||||
stopRegex byte = '}'
|
||||
|
||||
defaultRegexp = `[a-zA-Z0-9_\.]+`
|
||||
)
|
||||
|
||||
func pathCompiler(path string) (string, error) {
|
||||
var err error
|
||||
res := make([]byte, 0)
|
||||
var pos int = compContextPlain
|
||||
var depth int = 0
|
||||
pattern := make([]byte, 0)
|
||||
for _, b := range []byte(path) {
|
||||
switch pos {
|
||||
case compContextPlain:
|
||||
switch b {
|
||||
case stopRegex:
|
||||
depth -= 1
|
||||
res = append(res, b)
|
||||
case startRegex:
|
||||
depth += 1
|
||||
pos = compContextRegex // pattern started
|
||||
pattern = make([]byte, 0)
|
||||
default:
|
||||
res = append(res, b)
|
||||
}
|
||||
case compContextRegex:
|
||||
switch b {
|
||||
case startRegex:
|
||||
depth += 1
|
||||
case stopRegex:
|
||||
depth -= 1
|
||||
if depth == 0 {
|
||||
pattern = convertRegexp(pattern)
|
||||
res = append(res, pattern...)
|
||||
pos = compContextPlain // pattern ended
|
||||
}
|
||||
default:
|
||||
pattern = append(pattern, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
if depth != 0 {
|
||||
err = fmt.Errorf("Unbalanced brackets into pattern")
|
||||
}
|
||||
return string(res), err
|
||||
}
|
||||
|
||||
func convertRegexp(src []byte) []byte {
|
||||
var res string
|
||||
const patternSeps = ":"
|
||||
parts := strings.SplitN(string(src), patternSeps, 2)
|
||||
if len(parts) == 1 {
|
||||
parts = append(parts, defaultRegexp)
|
||||
}
|
||||
res = fmt.Sprintf("(?<%s>%s)", parts[0], parts[1])
|
||||
return []byte(res)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func tDebugf(msg string, args ...any) {
|
||||
fmt.Printf("debug: ")
|
||||
fmt.Printf(msg, args...)
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
|
||||
func TestPatchCompilerA(t *testing.T) {
|
||||
var err error
|
||||
srcPath := `/v1/file/{collection:[a-zA-Z]+}/{name}`
|
||||
reSource, err := pathCompiler(srcPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
tDebugf("re: %s\n", reSource)
|
||||
|
||||
re, err := regexp.Compile(reSource)
|
||||
require.NoError(t, err)
|
||||
reqPath := `/v1/file/foo/bare`
|
||||
match := re.MatchString(reqPath)
|
||||
require.True(t, match)
|
||||
|
||||
submatch := re.FindStringSubmatch(reqPath)
|
||||
subnames := re.SubexpNames()
|
||||
|
||||
submap := make(map[string]string)
|
||||
for i, val := range subnames {
|
||||
tDebugf("subname: %d = %s", i, val)
|
||||
}
|
||||
for i, val := range submatch {
|
||||
key := subnames[i]
|
||||
if key != "" {
|
||||
submap[key] = val
|
||||
}
|
||||
tDebugf("sub: %d = %s", i, val)
|
||||
}
|
||||
tDebugf("submap: %v", submap)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewRecoveryMiddleware(print func(string, ...any)) MiddlewareFunc {
|
||||
mw := func(next Handler) Handler {
|
||||
return newRecoveryHandler(next, print)
|
||||
}
|
||||
return mw
|
||||
}
|
||||
|
||||
type recoveryHandler struct {
|
||||
next Handler
|
||||
print func(string, ...any)
|
||||
}
|
||||
|
||||
func newRecoveryHandler(next Handler, print func(string, ...any)) *recoveryHandler {
|
||||
return &recoveryHandler{
|
||||
next: next,
|
||||
print: print,
|
||||
}
|
||||
}
|
||||
|
||||
func (hand recoveryHandler) ServeHTTP(rctx *Context) {
|
||||
exitFunc := func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
rctx.Writer.WriteHeader(http.StatusInternalServerError)
|
||||
stack := string(debug.Stack())
|
||||
timestamp := time.Now().Format(time.RFC3339)
|
||||
hand.print("%s %v ; %s\n", timestamp, err, stack)
|
||||
}
|
||||
}
|
||||
defer exitFunc()
|
||||
hand.next.ServeHTTP(rctx)
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type MiddlewareFunc func(next Handler) Handler
|
||||
|
||||
type Handler interface {
|
||||
ServeHTTP(rctx *Context)
|
||||
}
|
||||
|
||||
type HandlerFunc func(rctx *Context)
|
||||
|
||||
func (handlerFunc HandlerFunc) ServeHTTP(rctx *Context) {
|
||||
handlerFunc(rctx)
|
||||
}
|
||||
|
||||
type Router struct {
|
||||
headHandler Handler
|
||||
routeHandler *Selector
|
||||
}
|
||||
|
||||
func NewRouter() *Router {
|
||||
selector := NewSelector()
|
||||
return &Router{
|
||||
routeHandler: selector,
|
||||
headHandler: selector,
|
||||
}
|
||||
}
|
||||
|
||||
func (rout *Router) Use(mwFunc MiddlewareFunc) {
|
||||
rout.headHandler = mwFunc(rout.headHandler)
|
||||
}
|
||||
|
||||
func (rout *Router) Selector() *Selector {
|
||||
return rout.routeHandler
|
||||
}
|
||||
|
||||
func (rout *Router) AddRoute(method, path string, handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.AddRoute(method, path, handlerFunc)
|
||||
}
|
||||
|
||||
func (rout *Router) Head(path string, handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.AddRoute("HEAD", path, handlerFunc)
|
||||
}
|
||||
|
||||
func (rout *Router) Get(path string, handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.AddRoute("GET", path, handlerFunc)
|
||||
}
|
||||
|
||||
func (rout *Router) Post(path string, handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.AddRoute("POST", path, handlerFunc)
|
||||
}
|
||||
|
||||
func (rout *Router) Put(path string, handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.AddRoute("PUT", path, handlerFunc)
|
||||
}
|
||||
|
||||
func (rout *Router) Patch(path string, handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.AddRoute("PATCH", path, handlerFunc)
|
||||
}
|
||||
|
||||
func (rout *Router) Delete(path string, handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.AddRoute("DELETE", path, handlerFunc)
|
||||
}
|
||||
|
||||
func (rout *Router) Connect(path string, handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.AddRoute("CONNECT", path, handlerFunc)
|
||||
}
|
||||
|
||||
func (rout *Router) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
|
||||
rctx := NewContext(writer, req)
|
||||
rout.headHandler.ServeHTTP(rctx)
|
||||
}
|
||||
|
||||
func (rout *Router) NotFound(handlerFunc HandlerFunc) {
|
||||
rout.routeHandler.notFound = handlerFunc
|
||||
}
|
||||
|
||||
type Selector struct {
|
||||
Routes []*Route
|
||||
notFound Handler
|
||||
}
|
||||
|
||||
func NewSelector() *Selector {
|
||||
notFound := HandlerFunc(func(ctx *Context) {
|
||||
http.NotFound(ctx.Writer, ctx.Request)
|
||||
})
|
||||
return &Selector{
|
||||
Routes: make([]*Route, 0),
|
||||
notFound: notFound,
|
||||
}
|
||||
}
|
||||
|
||||
const globalRoutePattern = `^%s$`
|
||||
|
||||
func (hand *Selector) AddRoute(method, path string, handlerFunc HandlerFunc) error {
|
||||
var err error
|
||||
rawPath := path
|
||||
path, err = pathCompiler(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path = fmt.Sprintf(globalRoutePattern, path)
|
||||
re, err := regexp.Compile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
route := &Route{
|
||||
Method: method,
|
||||
Path: path,
|
||||
RawPath: rawPath,
|
||||
Handler: handlerFunc,
|
||||
Regexp: re,
|
||||
}
|
||||
hand.Routes = append(hand.Routes, route)
|
||||
return err
|
||||
}
|
||||
|
||||
func (hand *Selector) ServeHTTP(rctx *Context) {
|
||||
realHandler := hand.notFound
|
||||
for _, route := range hand.Routes {
|
||||
match := route.Match(rctx.Request)
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
subvals := route.Regexp.FindStringSubmatch(rctx.Request.URL.Path)
|
||||
subkeys := route.Regexp.SubexpNames()
|
||||
for i, val := range subvals {
|
||||
key := subkeys[i]
|
||||
if key != "" {
|
||||
rctx.PathMap[key] = val
|
||||
}
|
||||
}
|
||||
realHandler = route.Handler
|
||||
break
|
||||
}
|
||||
realHandler.ServeHTTP(rctx)
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
Method string
|
||||
Regexp *regexp.Regexp
|
||||
Path string
|
||||
RawPath string
|
||||
Handler HandlerFunc
|
||||
}
|
||||
|
||||
func (route Route) Match(req *http.Request) bool {
|
||||
if req.Method != route.Method {
|
||||
return false
|
||||
}
|
||||
match := route.Regexp.MatchString(req.URL.Path)
|
||||
if match {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRouterStatus(t *testing.T) {
|
||||
|
||||
reqPath := "/hello"
|
||||
handler := NewRouter()
|
||||
helloHandler := func(rctx *Context) {
|
||||
rctx.SetStatus(http.StatusOK)
|
||||
}
|
||||
handler.Get(reqPath, helloHandler)
|
||||
|
||||
request, err := http.NewRequest("GET", reqPath, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
fmt.Printf("Response code: %d\n", recorder.Code)
|
||||
}
|
||||
|
||||
func TestRouterSendText(t *testing.T) {
|
||||
testText := "hello, world"
|
||||
reqPath := "/hello"
|
||||
rout := NewRouter()
|
||||
helloHandler := func(rctx *Context) {
|
||||
rctx.SendText(http.StatusOK, testText)
|
||||
}
|
||||
rout.Get(reqPath, helloHandler)
|
||||
|
||||
request, err := http.NewRequest("GET", reqPath, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
rout.ServeHTTP(recorder, request)
|
||||
fmt.Printf("Response code: %d\n", recorder.Code)
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
bodyReader := recorder.Body
|
||||
bodyBytes, err := io.ReadAll(bodyReader)
|
||||
|
||||
fmt.Printf("Response body: %s\n", string(bodyBytes))
|
||||
require.Equal(t, string(bodyBytes), testText)
|
||||
}
|
||||
|
||||
func TestRouterSendJSON(t *testing.T) {
|
||||
|
||||
type testStruct struct {
|
||||
Message string `json:"message"`
|
||||
Code int64 `json:"code"`
|
||||
}
|
||||
testVar := testStruct{
|
||||
Message: "hello, world",
|
||||
Code: 123,
|
||||
}
|
||||
testData, err := json.Marshal(testVar)
|
||||
require.NoError(t, err)
|
||||
|
||||
reqPath := "/hello"
|
||||
handler := NewRouter()
|
||||
|
||||
helloHandler := func(rctx *Context) {
|
||||
rctx.SendJSON(http.StatusOK, &testVar)
|
||||
}
|
||||
handler.Get(reqPath, helloHandler)
|
||||
|
||||
request, err := http.NewRequest("GET", reqPath, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
fmt.Printf("Response code: %d\n", recorder.Code)
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
bodyReader := recorder.Body
|
||||
bodyBytes, err := io.ReadAll(bodyReader)
|
||||
require.NoError(t, err)
|
||||
bodyBytes = bytes.Trim(bodyBytes, "\n\r")
|
||||
|
||||
fmt.Printf("Response body: %s\n", string(bodyBytes))
|
||||
require.Equal(t, string(testData), string(bodyBytes))
|
||||
}
|
||||
|
||||
func TestRouterBindJSON(t *testing.T) {
|
||||
|
||||
type testStruct struct {
|
||||
Message string `json:"message"`
|
||||
Code int64 `json:code"`
|
||||
}
|
||||
testVar := testStruct{
|
||||
Message: "hello, world",
|
||||
Code: 123,
|
||||
}
|
||||
testData, err := json.Marshal(testVar)
|
||||
require.NoError(t, err)
|
||||
buffer := bytes.NewBuffer(testData)
|
||||
|
||||
reqPath := "/hello"
|
||||
handler := NewRouter()
|
||||
|
||||
helloHandler := func(rctx *Context) {
|
||||
handVar := testStruct{}
|
||||
rctx.BindJSON(&handVar)
|
||||
fmt.Printf("Received message: %s - %d\n", handVar.Message, handVar.Code)
|
||||
require.Equal(t, handVar.Code, int64(123))
|
||||
rctx.SendJSON(http.StatusOK, &handVar)
|
||||
}
|
||||
handler.Post(reqPath, helloHandler)
|
||||
|
||||
request, err := http.NewRequest("POST", reqPath, buffer)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
|
||||
fmt.Printf("Response code: %d\n", recorder.Code)
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
bodyReader := recorder.Body
|
||||
bodyBytes, err := io.ReadAll(bodyReader)
|
||||
require.NoError(t, err)
|
||||
bodyBytes = bytes.Trim(bodyBytes, "\n\r")
|
||||
|
||||
fmt.Printf("Response body: %s\n", string(bodyBytes))
|
||||
require.Equal(t, string(testData), string(bodyBytes))
|
||||
}
|
||||
|
||||
func TestRouterBindParams(t *testing.T) {
|
||||
|
||||
reqPath := "/hello"
|
||||
handler := NewRouter()
|
||||
|
||||
helloHandler := func(rctx *Context) {
|
||||
type Params struct {
|
||||
Name string `param:"name"`
|
||||
Code int64 `param:"code"`
|
||||
}
|
||||
params := &Params{}
|
||||
rctx.BindQuery(params)
|
||||
fmt.Printf("Received name: %s\n", params.Name)
|
||||
fmt.Printf("Received code: %d\n", params.Code)
|
||||
rctx.SendText(http.StatusOK, "hello")
|
||||
}
|
||||
handler.Get(reqPath, helloHandler)
|
||||
|
||||
reqPath = reqPath + `?name=world&code=123`
|
||||
request, err := http.NewRequest("GET", reqPath, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
|
||||
fmt.Printf("Response code: %d\n", recorder.Code)
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
|
||||
bodyReader := recorder.Body
|
||||
bodyBytes, err := io.ReadAll(bodyReader)
|
||||
require.NoError(t, err)
|
||||
bodyBytes = bytes.Trim(bodyBytes, "\n\r")
|
||||
|
||||
fmt.Printf("Response body: %s\n", string(bodyBytes))
|
||||
}
|
||||
|
||||
func BenchmarkLoggerL(b *testing.B) {
|
||||
reqPath := "/hello"
|
||||
helloHandler := func(rctx *Context) {
|
||||
rctx.SetStatus(http.StatusOK)
|
||||
}
|
||||
handler := NewRouter()
|
||||
handler.Get(reqPath, helloHandler)
|
||||
|
||||
request, err := http.NewRequest("GET", reqPath, nil)
|
||||
require.NoError(b, err)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
require.Equal(b, http.StatusOK, recorder.Code)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"mproxy/app/config"
|
||||
"mproxy/app/handler"
|
||||
"mproxy/app/logger"
|
||||
"mproxy/app/service"
|
||||
"mproxy/pkg/auxtool"
|
||||
|
||||
"mproxy/app/proxoper"
|
||||
"mproxy/app/servoper"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
conf *config.Config
|
||||
seop *servoper.Operator
|
||||
prop *proxoper.Operator
|
||||
svc *service.Service
|
||||
hand *handler.Handler
|
||||
logg *logger.Logger
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
wg sync.WaitGroup
|
||||
logf *os.File
|
||||
//x509cert []byte
|
||||
//x509key []byte
|
||||
listen net.Listener
|
||||
}
|
||||
|
||||
func NewServer() (*Server, error) {
|
||||
var err error
|
||||
srv := &Server{}
|
||||
srv.logg = logger.NewLoggerWithSubject("server")
|
||||
srv.ctx, srv.cancel = context.WithCancel(context.Background())
|
||||
return srv, err
|
||||
}
|
||||
|
||||
func (srv *Server) Handler() *handler.Handler {
|
||||
return srv.hand
|
||||
}
|
||||
|
||||
func (srv *Server) Service() *service.Service {
|
||||
return srv.svc
|
||||
}
|
||||
|
||||
func (srv *Server) SetLogdir(dir string) {
|
||||
srv.conf.Logpath = dir
|
||||
}
|
||||
|
||||
func (srv *Server) SetRundir(dir string) {
|
||||
srv.conf.Runpath = dir
|
||||
}
|
||||
|
||||
func (srv *Server) SetDatadir(dir string) {
|
||||
srv.conf.Database.Basepath = dir
|
||||
srv.conf.Storage.Basepath = dir
|
||||
srv.conf.Datadir = dir
|
||||
}
|
||||
|
||||
func (srv *Server) SetPort(port uint32) {
|
||||
srv.conf.Service.Port = port
|
||||
}
|
||||
|
||||
func (srv *Server) SetAsDaemon(asDaemon bool) {
|
||||
srv.conf.AsDaemon = asDaemon
|
||||
}
|
||||
|
||||
func (srv *Server) Configure() error {
|
||||
var err error
|
||||
//srv.logg.Infof("Configuration server")
|
||||
srv.conf = config.NewConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = srv.conf.ReadConfigfile()
|
||||
if err != nil {
|
||||
srv.logg.Warningf("Error loading config file: %v", err)
|
||||
err = nil
|
||||
}
|
||||
err = srv.conf.ReadX509Cert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) Build() error {
|
||||
var err error
|
||||
//srv.logg.Infof("Server building")
|
||||
|
||||
currUser, err := user.Current()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error getting current user: %v\n", err)
|
||||
return err
|
||||
}
|
||||
cuid64, err := strconv.ParseInt(currUser.Uid, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cgid64, err := strconv.ParseInt(currUser.Gid, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
euid := int(cuid64)
|
||||
egid := int(cgid64)
|
||||
if cuid64 == 0 {
|
||||
usr, err := user.Lookup(srv.conf.RunUser)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uid64, err := strconv.ParseInt(usr.Uid, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gid64, err := strconv.ParseInt(usr.Gid, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
euid = int(uid64)
|
||||
egid = int(gid64)
|
||||
}
|
||||
// Creating datadir
|
||||
datadir := srv.conf.Datadir
|
||||
if !auxtool.DirExists(datadir) { // TODO: check access to dir
|
||||
//srv.logg.Infof("Creating data directory %s ", datadir)
|
||||
err = os.MkdirAll(datadir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = os.Chown(datadir, euid, egid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if srv.conf.AsDaemon {
|
||||
logdir := filepath.Dir(srv.conf.Logpath)
|
||||
//srv.logg.Infof("Creating log directory %s", logdir)
|
||||
err = os.MkdirAll(logdir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chown(logdir, euid, egid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rundir := filepath.Dir(srv.conf.Runpath)
|
||||
//srv.logg.Infof("Creating run directory %s", rundir)
|
||||
err = os.MkdirAll(rundir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chown(rundir, euid, egid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Redirect stderr and stout
|
||||
logFile, err := os.OpenFile(srv.conf.Logpath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Dup2(int(logFile.Fd()), int(os.Stdout.Fd()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.logf = logFile
|
||||
}
|
||||
|
||||
confDump := srv.conf.String()
|
||||
srv.logg.Infof("Current server configuration is:\n%s\n", confDump)
|
||||
|
||||
if cuid64 == 0 {
|
||||
// Change effective user and group
|
||||
err = syscall.Setgid(egid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Setuid(euid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
//return fmt.Errorf("Debug break")
|
||||
|
||||
uidstr := strconv.FormatInt(int64(syscall.Geteuid()), 10)
|
||||
usr, err := user.LookupId(uidstr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.logg.Warningf("Now run as user: %s", usr.Username)
|
||||
|
||||
// Creating service operator
|
||||
srv.logg.Infof("Creating operator")
|
||||
servoperParams := &servoper.OperatorParams{}
|
||||
srv.seop, err = servoper.NewOperator(servoperParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Creating proxy operator
|
||||
srv.logg.Infof("Creating operator")
|
||||
proxoperParams := &proxoper.OperatorParams{}
|
||||
srv.prop, err = proxoper.NewOperator(proxoperParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Creating handler
|
||||
srv.logg.Infof("Creating handler")
|
||||
handlerParams := &handler.HandlerParams{
|
||||
ServOper: srv.seop,
|
||||
ProxOper: srv.prop,
|
||||
}
|
||||
srv.hand, err = handler.NewHandler(handlerParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Creating service
|
||||
serviceParams := &service.ServiceParams{
|
||||
Handler: srv.hand,
|
||||
X509cert: srv.conf.X509Cert,
|
||||
X509key: srv.conf.X509Key,
|
||||
Address: srv.conf.Service.Address,
|
||||
Portnum: srv.conf.Service.Port,
|
||||
}
|
||||
srv.logg.Infof("Creating service")
|
||||
srv.svc, err = service.NewService(serviceParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Building service
|
||||
err = srv.svc.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) Run() error {
|
||||
var err error
|
||||
|
||||
if srv.conf.AsDaemon {
|
||||
// Redirect stdin
|
||||
nullFile, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Dup2(int(nullFile.Fd()), int(os.Stdin.Fd()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write process ID
|
||||
pidFile, err := os.OpenFile(srv.conf.Runpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pidFile.Close()
|
||||
currPid := os.Getpid()
|
||||
_, err = pidFile.WriteString(strconv.Itoa(currPid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Start log rotator
|
||||
srv.Rotator()
|
||||
}
|
||||
|
||||
currUser, err := user.Current()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.logg.Infof("Server started with user: %s", currUser.Username)
|
||||
uidstr := strconv.FormatInt(int64(syscall.Geteuid()), 10)
|
||||
usr, err := user.LookupId(uidstr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.logg.Infof("Server run with user: %s", usr.Username)
|
||||
|
||||
svcDone := make(chan error, 1)
|
||||
// Service run
|
||||
srv.logg.Infof("Start service")
|
||||
startService := func(svc *service.Service, done chan error) {
|
||||
err = svc.Run()
|
||||
if err != nil {
|
||||
srv.logg.Errorf("Service error: %v", err)
|
||||
done <- err
|
||||
}
|
||||
}
|
||||
go startService(srv.svc, svcDone)
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
var signal os.Signal
|
||||
|
||||
select {
|
||||
case signal = <-sigs:
|
||||
srv.logg.Infof("Services stopped by signal: %v", signal)
|
||||
srv.cancel()
|
||||
srv.svc.Stop()
|
||||
srv.wg.Wait()
|
||||
case err = <-svcDone:
|
||||
srv.logg.Infof("Service stopped by service error: %v", err)
|
||||
srv.cancel()
|
||||
srv.svc.Stop()
|
||||
srv.wg.Wait()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) PseudoFork() error {
|
||||
const successExit int = 0
|
||||
var keyEnv string = "IMX0LTSELMRF8K"
|
||||
var err error
|
||||
|
||||
_, isChild := os.LookupEnv(keyEnv)
|
||||
switch {
|
||||
case !isChild:
|
||||
os.Setenv(keyEnv, "TRUE")
|
||||
|
||||
procAttr := syscall.ProcAttr{}
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var sysFiles = make([]uintptr, 3)
|
||||
sysFiles[0] = uintptr(syscall.Stdin)
|
||||
sysFiles[1] = uintptr(syscall.Stdout)
|
||||
sysFiles[2] = uintptr(syscall.Stderr)
|
||||
|
||||
procAttr.Files = sysFiles
|
||||
procAttr.Env = os.Environ()
|
||||
procAttr.Dir = cwd
|
||||
|
||||
_, err = syscall.ForkExec(os.Args[0], os.Args, &procAttr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Exit(successExit)
|
||||
case isChild:
|
||||
_, err = syscall.Setsid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
os.Unsetenv(keyEnv)
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) Daemonize() error {
|
||||
var err error
|
||||
if srv.conf.AsDaemon {
|
||||
// Restart process process
|
||||
err = srv.PseudoFork()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) Rotator() {
|
||||
srv.wg.Add(1)
|
||||
var counter uint64
|
||||
logFunc := func() {
|
||||
for {
|
||||
counter += 1
|
||||
select {
|
||||
case <-srv.ctx.Done():
|
||||
srv.wg.Done()
|
||||
srv.logg.Infof("Log file rotator done")
|
||||
return
|
||||
default:
|
||||
}
|
||||
if (counter % 60) == 1 {
|
||||
stat, err := srv.logf.Stat()
|
||||
if err == nil && stat.Size() > srv.conf.LogLimit {
|
||||
srv.logg.Infof("Rotate log file")
|
||||
countFiles := 3
|
||||
for i := 1; i < countFiles; i++ {
|
||||
nextName := fmt.Sprintf("%s.%d", srv.conf.Logpath, i+1)
|
||||
prevName := fmt.Sprintf("%s.%d", srv.conf.Logpath, i)
|
||||
os.Rename(prevName, nextName)
|
||||
}
|
||||
os.Rename(srv.conf.Logpath, srv.conf.Logpath+".1")
|
||||
logFile, err := os.OpenFile(srv.conf.Logpath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
|
||||
if err == nil {
|
||||
syscall.Dup2(int(logFile.Fd()), int(os.Stdout.Fd()))
|
||||
syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
|
||||
srv.logf.Close()
|
||||
srv.logf = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
go logFunc()
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"mproxy/app/handler"
|
||||
"mproxy/app/logger"
|
||||
"mproxy/app/router"
|
||||
)
|
||||
|
||||
type ServiceParams struct {
|
||||
Handler *handler.Handler
|
||||
Address string
|
||||
Portnum uint32
|
||||
X509cert string
|
||||
X509key string
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
hand *handler.Handler
|
||||
rout *router.Router
|
||||
logg *logger.Logger
|
||||
hsrv *http.Server
|
||||
|
||||
address string
|
||||
portnum uint32
|
||||
listen net.Listener
|
||||
x509cert string
|
||||
x509key string
|
||||
protocol string
|
||||
}
|
||||
|
||||
func NewService(params *ServiceParams) (*Service, error) {
|
||||
var err error
|
||||
svc := &Service{
|
||||
hand: params.Handler,
|
||||
address: params.Address,
|
||||
portnum: params.Portnum,
|
||||
x509cert: params.X509cert,
|
||||
x509key: params.X509key,
|
||||
protocol: "TCP",
|
||||
}
|
||||
svc.logg = logger.NewLoggerWithSubject("service")
|
||||
return svc, err
|
||||
}
|
||||
|
||||
func (svc *Service) Build() error {
|
||||
var err error
|
||||
svc.logg.Infof("Service build ")
|
||||
|
||||
svc.rout = router.NewRouter()
|
||||
|
||||
svc.rout.Use(router.NewRecoveryMiddleware(svc.logg.Errorf))
|
||||
svc.rout.Use(router.NewLoggingMiddleware(svc.logg.Infof))
|
||||
svc.rout.Use(router.NewCorsMiddleware())
|
||||
svc.rout.Use(svc.hand.AuthMiddleware)
|
||||
|
||||
svc.rout.Get(`/v3/api/service/hello`, svc.hand.SendHello)
|
||||
svc.rout.Connect(`{hostaddr}`, svc.hand.ConnectTo)
|
||||
|
||||
svc.rout.NotFound(svc.hand.NotFound)
|
||||
|
||||
selector := svc.rout.Selector()
|
||||
for _, item := range selector.Routes {
|
||||
svc.logg.Infof("%s\t%s", item.Method, item.RawPath)
|
||||
}
|
||||
|
||||
const useTLS = true
|
||||
if useTLS {
|
||||
tlsCert, err := tls.X509KeyPair([]byte(svc.x509cert), []byte(svc.x509key))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tlsConfig := tls.Config{
|
||||
Certificates: []tls.Certificate{tlsCert},
|
||||
ClientAuth: tls.NoClientCert,
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
listenAddress := fmt.Sprintf("%s:%d", svc.address, svc.portnum)
|
||||
svc.listen, err = tls.Listen(svc.protocol, listenAddress, &tlsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
} else {
|
||||
listenAddress := fmt.Sprintf("%s:%d", svc.address, svc.portnum)
|
||||
svc.listen, err = net.Listen(svc.protocol, listenAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
svc.logg.Infof("Service listening at %v", svc.listen.Addr())
|
||||
svc.hsrv = &http.Server{
|
||||
Handler: svc.rout,
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (svc *Service) Run() error {
|
||||
var err error
|
||||
svc.logg.Infof("Service run")
|
||||
err = svc.hsrv.Serve(svc.listen)
|
||||
if err == http.ErrServerClosed {
|
||||
svc.logg.Warningf("Service Closed")
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (svc *Service) Stop() {
|
||||
if svc.hsrv != nil {
|
||||
svc.logg.Infof("Service stop")
|
||||
downWaiting := 10 * time.Second
|
||||
ctx, cancel := context.WithTimeout(context.Background(), downWaiting)
|
||||
defer cancel()
|
||||
err := svc.hsrv.Shutdown(ctx)
|
||||
if err != nil {
|
||||
svc.logg.Errorf("Error service shutdown: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package servoper
|
||||
|
||||
import (
|
||||
"mproxy/app/logger"
|
||||
)
|
||||
|
||||
type OperatorParams struct{}
|
||||
|
||||
type Operator struct {
|
||||
logg *logger.Logger
|
||||
}
|
||||
|
||||
func NewOperator(params *OperatorParams) (*Operator, error) {
|
||||
var err error
|
||||
oper := &Operator{}
|
||||
oper.logg = logger.NewLoggerWithSubject("servoper")
|
||||
return oper, err
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package servoper
|
||||
|
||||
type SendHelloParams struct{}
|
||||
|
||||
type SendHelloResult struct {
|
||||
Message string `json:"message"`
|
||||
Alive bool `json:"alive"`
|
||||
}
|
||||
|
||||
func (oper *Operator) SendHello(param *SendHelloParams) (*SendHelloResult, error) {
|
||||
var err error
|
||||
res := &SendHelloResult{
|
||||
Alive: true,
|
||||
Message: "hello",
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"mproxy/cmd/mproxyctl/util"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
util := util.NewUtil()
|
||||
err = util.Build()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
err = util.Exec(os.Args[1:])
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type Util struct {
|
||||
rootCmd *cobra.Command
|
||||
}
|
||||
|
||||
func NewUtil() *Util {
|
||||
return &Util{}
|
||||
}
|
||||
|
||||
func (util *Util) GetRooCmd() *cobra.Command {
|
||||
return util.rootCmd
|
||||
}
|
||||
|
||||
func (util *Util) Build() error {
|
||||
var err error
|
||||
execName := filepath.Base(os.Args[0])
|
||||
rootCmd := &cobra.Command{
|
||||
Use: execName,
|
||||
Short: "\nOperation with artefacts: files, images, service accounts and grants",
|
||||
SilenceUsage: true,
|
||||
}
|
||||
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||
util.rootCmd = rootCmd
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (util *Util) Exec(args []string) error {
|
||||
var err error
|
||||
util.rootCmd.SetArgs(args)
|
||||
err = util.rootCmd.Execute()
|
||||
return err
|
||||
}
|
||||
|
||||
func (util *Util) Hello(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("hello, world!")
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"mproxy/app/logger"
|
||||
"mproxy/cmd/mproxyd/starter"
|
||||
|
||||
_ "mproxy/app/handler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log := logger.NewLoggerWithSubject("main")
|
||||
sta := starter.NewStarter()
|
||||
err := sta.Exec()
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package starter
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"mproxy/app/server"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type Starter struct {
|
||||
runAsDaemon bool
|
||||
port uint32
|
||||
cmd *cobra.Command
|
||||
srv *server.Server
|
||||
}
|
||||
|
||||
func NewStarter() *Starter {
|
||||
execName := filepath.Base(os.Args[0])
|
||||
sta := &Starter{}
|
||||
cmd := &cobra.Command{
|
||||
Use: execName,
|
||||
Short: "\nArtifact storage service",
|
||||
SilenceUsage: true,
|
||||
RunE: sta.run,
|
||||
}
|
||||
cmd.CompletionOptions.DisableDefaultCmd = true
|
||||
cmd.Flags().BoolVarP(&sta.runAsDaemon, "asDaemon", "D", true, "Run service as daemon")
|
||||
cmd.Flags().Uint32VarP(&sta.port, "port", "P", 1025, "Service port")
|
||||
|
||||
sta.cmd = cmd
|
||||
return sta
|
||||
}
|
||||
|
||||
func (sta *Starter) GetCmd() *cobra.Command {
|
||||
return sta.cmd
|
||||
}
|
||||
|
||||
func (sta *Starter) run(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
srv, err := server.NewServer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = srv.Configure()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.SetAsDaemon(sta.runAsDaemon)
|
||||
srv.SetPort(sta.port)
|
||||
|
||||
err = srv.Daemonize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = srv.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = srv.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sta.srv = srv
|
||||
return err
|
||||
}
|
||||
|
||||
func (sta *Starter) Exec() error {
|
||||
return sta.cmd.Execute()
|
||||
}
|
||||
+1815
File diff suppressed because it is too large
Load Diff
+2354
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+256
@@ -0,0 +1,256 @@
|
||||
AC_INIT([mproxy],[0.0.1])
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax])
|
||||
AC_PREFIX_DEFAULT(/usr/local)
|
||||
|
||||
PACKAGE=mproxy
|
||||
|
||||
AC_CHECK_PROG(HAVE_GO, go, true, false)
|
||||
if test "x$HAVE_GO" = "xfalse"; then
|
||||
AC_MSG_ERROR([Requested program go not found])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG([GO],[go])
|
||||
AC_PATH_PROG([FIND],[find])
|
||||
AC_PATH_PROG([XARGS],[xargs])
|
||||
AC_PATH_PROG([SORT],[sort])
|
||||
AC_PATH_PROG([UNIQ],[uniq])
|
||||
AC_PATH_PROGS([SUDO],[sudo false])
|
||||
AC_PATH_PROGS([CPIO],[cpio false])
|
||||
AC_PATH_PROGS([BASENAME],[basename])
|
||||
|
||||
AC_PATH_PROGS([PODMAN],[podman true])
|
||||
AC_PATH_PROGS([HELM],[helm true])
|
||||
AC_PATH_PROGS([DBUILDPACKAGE],[dpkg-buildpackage true])
|
||||
AC_PATH_PROGS([DPKGSOURCE],[dpkg-source true])
|
||||
AC_PATH_PROGS([SWAG],[swag true])
|
||||
|
||||
|
||||
AC_PATH_PROGS([CP],[gcp cp])
|
||||
if test -z "$CP"; then
|
||||
AC_MSG_ERROR([Requested program cp not found])
|
||||
fi
|
||||
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_MKDIR_P
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
case $host_os in
|
||||
*freebsd* )
|
||||
AC_SUBST(ROOT_GROUP, "wheel")
|
||||
AM_CONDITIONAL(FREEBSD_OS, true)
|
||||
AM_CONDITIONAL(LINUX_OS, false)
|
||||
OSNAME=freebsd
|
||||
ROOT_GROUP=wheel
|
||||
;;
|
||||
*linux* )
|
||||
AC_SUBST(ROOT_GROUP, "root")
|
||||
AM_CONDITIONAL(FREEBSD_OS, false)
|
||||
AM_CONDITIONAL(LINUX_OS, true)
|
||||
OSNAME=linux
|
||||
ROOT_GROUP=root
|
||||
;;
|
||||
esac
|
||||
|
||||
AM_CONDITIONAL(SYSTEMD, false)
|
||||
if test -d /lib/systemd/system; then
|
||||
AM_CONDITIONAL(SYSTEMD, true)
|
||||
fi
|
||||
|
||||
|
||||
test "x$prefix" == "xNONE" && prefix=$ac_default_prefix
|
||||
test "x$libexecdir" == "xNONE" && libexecdir=${prefix}/lib
|
||||
|
||||
|
||||
dnl --------------------------------------------------------------------------------------
|
||||
|
||||
AC_ARG_ENABLE([devel-mode],
|
||||
AS_HELP_STRING([--enable-devel-mode], [Enable developmend mode]))
|
||||
|
||||
|
||||
AC_DEFINE_UNQUOTED(srv_devel_mode, "false", [developmend mode])
|
||||
AC_SUBST(srv_devel_mode, "false")
|
||||
|
||||
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||
SRCDIR=`pwd`
|
||||
enable_devel_mode=yes
|
||||
])
|
||||
|
||||
dnl --------------------------------------------------------------------------------------
|
||||
|
||||
SRV_CONFDIR="${prefix}/etc/${PACKAGE}"
|
||||
|
||||
AC_ARG_WITH(confdir,
|
||||
AS_HELP_STRING([--with-confdir=PATH],[set configuration dir to PATH (default: $SRV_CONFDIR)]),
|
||||
[ if test ! -z "$withval" ; then
|
||||
case $withval in
|
||||
/*)
|
||||
SRV_CONFDIR="$withval"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(You must specify an absolute path to --with-confdir=PATH)
|
||||
;;
|
||||
esac
|
||||
fi ])
|
||||
|
||||
|
||||
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||
SRV_CONFDIR="${SRCDIR}/etc/${PACKAGE}"
|
||||
sysconfdir="${SRCDIR}/etc/${PACKAGE}"
|
||||
], [
|
||||
test "x$SRV_CONFDIR" == "x/usr/etc/${PACKAGE}" && SRV_CONFDIR="/etc/${PACKAGE}"
|
||||
test "x$prefix" == "x/usr" && sysconfdir="/etc"
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED(SRV_CONFDIR, "$SRV_CONFDIR", [location of configuration files for ${PACKAGE}])
|
||||
AC_SUBST(srv_confdir, "$SRV_CONFDIR")
|
||||
|
||||
AC_MSG_NOTICE(srv_confdir set as ${SRV_CONFDIR})
|
||||
|
||||
dnl --------------------------------------------------------------------------------------
|
||||
|
||||
SRV_LOGDIR="/var/log/${PACKAGE}"
|
||||
|
||||
AC_ARG_WITH(logdir,
|
||||
AS_HELP_STRING([--with-logdir=PATH],[set path for logdir (default: $SRV_LOGDIR)]),
|
||||
[ if test ! -z "$withval" ; then
|
||||
case $withval in
|
||||
/*)
|
||||
SRV_LOGDIR="$withval"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(You must specify an absolute path to --with-logdir=PATH)
|
||||
;;
|
||||
esac
|
||||
fi])
|
||||
|
||||
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||
SRV_LOGDIR="${SRCDIR}/tmp/log"
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED(SRV_LOGDIR, "$SRV_LOGDIR", [location of ${PACKAGE} logdir])
|
||||
AC_SUBST(srv_logdir, "$SRV_LOGDIR")
|
||||
|
||||
AC_MSG_NOTICE(srv_logdir set as ${SRV_LOGDIR})
|
||||
|
||||
dnl --------------------------------------------------------------------------------------
|
||||
|
||||
SRV_RUNDIR="/var/run/${PACKAGE}"
|
||||
|
||||
AC_ARG_WITH(rundir,
|
||||
AS_HELP_STRING([--with-rundir=PATH],[set path for rundir (default: $SRV_RUNDIR)]),
|
||||
[ if test ! -z "$withval" ; then
|
||||
case $withval in
|
||||
/*)
|
||||
SRV_RUNDIR="$withval"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(You must specify an absolute path to --with-rundir=PATH)
|
||||
;;
|
||||
esac
|
||||
fi ])
|
||||
|
||||
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||
SRV_RUNDIR="${SRCDIR}/tmp/run"
|
||||
])
|
||||
|
||||
|
||||
AC_DEFINE_UNQUOTED(SRV_RUNDIR, "$SRV_RUNDIR", [location of rundir])
|
||||
AC_SUBST(srv_rundir, "$SRV_RUNDIR")
|
||||
|
||||
AC_MSG_NOTICE(srv_rundir set as ${SRV_RUNDIR})
|
||||
|
||||
dnl --------------------------------------------------------------------------------------
|
||||
|
||||
SRV_SHAREDIR="${prefix}/share/$PACKAGE"
|
||||
|
||||
AC_ARG_WITH(sharedir,
|
||||
AS_HELP_STRING([--with-sharedir=PATH],[set share directory (default: $SRV_SHAREDIR)]),
|
||||
[ if test ! -z "$with_sharedir" ; then
|
||||
case $with_sharedir in
|
||||
/*)
|
||||
SRV_SHAREDIR="$withval"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(You must specify an absolute path to --with-sharedir=PATH)
|
||||
;;
|
||||
esac
|
||||
fi ])
|
||||
|
||||
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||
SRV_SHAREDIR="${SRCDIR}/share"
|
||||
])
|
||||
|
||||
|
||||
AC_DEFINE_UNQUOTED(SRV_SHAREDIR, "$SRV_SHAREDIR", [location of share dir])
|
||||
AC_SUBST(srv_sharedir, "$SRV_SHAREDIR")
|
||||
|
||||
AC_MSG_NOTICE(srv_sharedir set as ${SRV_SHAREDIR})
|
||||
|
||||
dnl --------------------------------------------------------------------------------------
|
||||
|
||||
SRV_LIBDIR="${prefix}/lib/$PACKAGE"
|
||||
|
||||
AC_ARG_WITH(libdir,
|
||||
AS_HELP_STRING([--with-libdir=PATH],[set lib directory (default: $SRV_LIBDIR)]),
|
||||
[ if test ! -z "$withval" ; then
|
||||
case $withval in
|
||||
/*)
|
||||
SRV_LIBDIR="$withval"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(You must specify an absolute path to --with-libdir=PATH)
|
||||
;;
|
||||
esac
|
||||
fi ])
|
||||
|
||||
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||
SRV_LIBDIR="${SRCDIR}/sysagent"
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED(SRV_LIBDIR, "$SRV_LIBDIR", [location of lib dir])
|
||||
AC_SUBST(srv_libdir, "$SRV_LIBDIR")
|
||||
|
||||
AC_MSG_NOTICE(srv_libdir set as ${SRV_LIBDIR})
|
||||
|
||||
dnl --------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
SRV_DATADIR="/var/lib/${PACKAGE}"
|
||||
|
||||
AC_ARG_WITH(datadir,
|
||||
AS_HELP_STRING([--with-datadir=PATH],[set path for datadir (default: $SRV_DATADIR)]),
|
||||
[ if test ! -z "$withval" ; then
|
||||
case $withval in
|
||||
/*)
|
||||
SRV_DATADIR="$withval"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(You must specify an absolute path to --with-datadir=PATH)
|
||||
;;
|
||||
esac
|
||||
fi])
|
||||
|
||||
AS_IF([test "x$enable_devel_mode" = "xyes"], [
|
||||
SRV_DATADIR="${SRCDIR}/tmp/data"
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED(SRV_DATADIR, "$SRV_DATADIR", [location of ${PACKAGE} datadir])
|
||||
AC_SUBST(srv_datadir, "$SRV_DATADIR")
|
||||
|
||||
AC_MSG_NOTICE(srv_datadir set as ${SRV_DATADIR})
|
||||
|
||||
dnl --------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
AM_EXTRA_RECURSIVE_TARGETS([docs])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
app/config/variant.go
|
||||
initrc/mproxyd.service
|
||||
initrc/mproxyd
|
||||
debian/control
|
||||
debian/changelog
|
||||
mans/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
@@ -0,0 +1,4 @@
|
||||
changelog
|
||||
control
|
||||
*~
|
||||
tmp
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
mbase for Debian
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
mbase (@PACKAGE_VERSION@-1) unstable; urgency=low
|
||||
|
||||
* Release.
|
||||
|
||||
-- Oleg Borodin <borodin@unix7.org> Sun, 29 Oct 2017 18:57:56 +0200
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
10
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
Source: mbase
|
||||
Section: utils
|
||||
Priority: extra
|
||||
Maintainer: borodin@unix7.org
|
||||
Build-Depends: debhelper (>=8)
|
||||
Standards-Version: @PACKAGE_VERSION@
|
||||
Homepage: http://wiki.unix7.org
|
||||
|
||||
Package: mbase-control
|
||||
Description: mbase
|
||||
Architecture: amd64
|
||||
|
||||
Package: mbase-service
|
||||
Description: mbase
|
||||
Architecture: amd64
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
mstore-control-dbgsym_2.11.0-1_amd64.deb debug optional automatic=yes
|
||||
mstore-control_2.11.0-1_amd64.deb utils extra
|
||||
mstore-service-dbgsym_2.11.0-1_amd64.deb debug optional automatic=yes
|
||||
mstore-service_2.11.0-1_amd64.deb utils extra
|
||||
mstore_2.11.0-1_amd64.buildinfo utils extra
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
usr/bin/mstorectl
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
usr/sbin/mstored
|
||||
lib/systemd/system/mstored.service
|
||||
var/run/mstore
|
||||
var/log/mstore
|
||||
etc/mstore
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ "$1" = "configure" ] ; then
|
||||
# Initial installation
|
||||
systemctl preset mstored.service >/dev/null 2>&1 || :
|
||||
fi
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
systemctl daemon-reload >/dev/null 2>&1 || :
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then
|
||||
# Package removal, not upgrade
|
||||
systemctl --no-reload disable mstored.service > /dev/null 2>&1 || :
|
||||
systemctl stop mstored.service > /dev/null 2>&1 || :
|
||||
fi
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
# You must remove unused comment lines for the released package.
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
export GO111MODULE=on
|
||||
export GOPROXY=https://proxy.golang.org
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_configure:
|
||||
./configure --prefix=/usr
|
||||
|
||||
|
||||
#EOF
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
||||
Vendored
Vendored
+1
@@ -0,0 +1 @@
|
||||
version=3
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
MimeType: application/vnd.oci.image.manifest.v1+json
|
||||
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"config": {
|
||||
"mediaType": "application/vnd.cncf.helm.config.v1+json",
|
||||
"digest": "sha256:33e3759271a3c6dc018541cfb73653c267df6f8ee28ce68e38c72e22196a1d87",
|
||||
"size": 126
|
||||
},
|
||||
"layers": [{
|
||||
"mediaType": "application/vnd.cncf.helm.chart.content.v1.tar+gzip",
|
||||
"digest": "sha256:93dc97d49c453a7ce3af622cf7ef698548045e0c09907c6a021018f6eac6c31a",
|
||||
"size": 1528
|
||||
}],
|
||||
"annotations": {
|
||||
"org.opencontainers.image.created": "2026-02-25T19:59:44+02:00",
|
||||
"org.opencontainers.image.description": "mStore service",
|
||||
"org.opencontainers.image.title": "mstore",
|
||||
"org.opencontainers.image.version": "0.2.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/27.0.9 Chrome/134.0.6998.205 Electron/35.4.0 Safari/537.36" version="27.0.9">
|
||||
<diagram name="Page-1" id="bilFRRFyBUGthtbaxYIo">
|
||||
<mxGraphModel dx="1880" dy="566" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-28" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F0FDFF;glass=0;strokeColor=#0e8088;" vertex="1" parent="1">
|
||||
<mxGeometry x="-10" y="55" width="120" height="335" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-26" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F0FDFF;glass=0;strokeColor=#0e8088;" vertex="1" parent="1">
|
||||
<mxGeometry x="120" y="50" width="630" height="350" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-5" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-1" target="t6Klk0bs08zzC_b7PXua-2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-30" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;exitX=0.75;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-2" target="t6Klk0bs08zzC_b7PXua-29">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-2" value="service" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="250" y="230" width="80" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-11" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;strokeColor=#000099;exitX=0.75;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-3" target="t6Klk0bs08zzC_b7PXua-8">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-19" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeColor=#0000CC;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-20" target="t6Klk0bs08zzC_b7PXua-17">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-3" value="handler" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
|
||||
<mxGeometry x="390" y="150" width="90" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-7" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.75;entryDx=0;entryDy=0;curved=0;strokeColor=#000099;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-6" target="t6Klk0bs08zzC_b7PXua-2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-6" value="client" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad7ac;strokeColor=#b46504;" vertex="1" parent="1">
|
||||
<mxGeometry x="10" y="240" width="90" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-12" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;strokeColor=#000099;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-8" target="t6Klk0bs08zzC_b7PXua-9">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-18" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-8" target="t6Klk0bs08zzC_b7PXua-17">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-23" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-8" target="t6Klk0bs08zzC_b7PXua-10">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-8" value="operator" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
|
||||
<mxGeometry x="500" y="230" width="90" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-9" value="storage" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1">
|
||||
<mxGeometry x="570" y="300" width="90" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-10" value="lockers" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#bac8d3;strokeColor=#23445d;" vertex="1" parent="1">
|
||||
<mxGeometry x="550" y="150" width="70" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-16" value="starter" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
||||
<mxGeometry x="140" y="110" width="80" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-33" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.25;exitDx=0;exitDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-1" target="t6Klk0bs08zzC_b7PXua-32">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-1" value="server" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
||||
<mxGeometry x="150" y="145" width="80" height="55" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-17" value="database" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1">
|
||||
<mxGeometry x="630" y="220" width="90" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-20" value="auth" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="120" width="50" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-31" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-29" target="t6Klk0bs08zzC_b7PXua-3">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-29" value="router" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
|
||||
<mxGeometry x="290" y="140" width="70" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-32" value="config" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1">
|
||||
<mxGeometry x="290" y="70" width="70" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="t6Klk0bs08zzC_b7PXua-34" value="Feb 2026<div>O Borodin</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeColor=default;" vertex="1" parent="1">
|
||||
<mxGeometry x="510" y="430" width="110" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"config": {
|
||||
"mediaType": "application/vnd.oci.image.config.v1+json",
|
||||
"digest": "sha256:2f99832d1fc23ae7c8a35d5aa0b9d7a78a1876d69f9453d5d6e8701ac86c171c",
|
||||
"size": 1357
|
||||
},
|
||||
"layers": [{
|
||||
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||
"digest": "sha256:7319607d119c259e90382101fb3ed98ad62e29ed817338183b3775dcfb358140",
|
||||
"size": 3731518
|
||||
}, {
|
||||
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||
"digest": "sha256:1fccc5cb3c84a43c9dec4d89f1383471b41e1c4b9d4f271e3c952839f76634f5",
|
||||
"size": 15791440
|
||||
}, {
|
||||
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||
"digest": "sha256:8cc3f2f15e1a38f6b733038dd9b3b27a88d4882a78a3235416f792dd9deca7af",
|
||||
"size": 173
|
||||
}],
|
||||
"annotations": {
|
||||
"com.docker.official-images.bashbrew.arch": "amd64",
|
||||
"org.opencontainers.image.base.digest": "sha256:b0cb30c51c47cdfde647364301758b14c335dea2fddc9490d4f007d67ecb2538",
|
||||
"org.opencontainers.image.base.name": "docker.io/library/alpine:3.20",
|
||||
"org.opencontainers.image.created": "2026-01-28T01:18:13Z",
|
||||
"org.opencontainers.image.revision": "b3f87708e5052e29737a251b2e9865e182dafe0c",
|
||||
"org.opencontainers.image.source": "https://github.com/alpinelinux/docker-alpine.git#b3f87708e5052e29737a251b2e9865e182dafe0c:x86_64",
|
||||
"org.opencontainers.image.url": "https://hub.docker.com/_/alpine",
|
||||
"org.opencontainers.image.version": "3.20.9"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEojCCBCmgAwIBAgISBpbPr7WFeCJ3U8QDioKGHkQiMAoGCCqGSM49BAMDMDIx
|
||||
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
|
||||
ODAeFw0yNjAyMTIwOTExMDVaFw0yNjA1MTMwOTExMDRaMBgxFjAUBgNVBAMTDWRl
|
||||
di51bml4Ny5vcmcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATZnNwUA6M5kqmq
|
||||
36oRkUTC+fSPlLiLDs3Vz6fPdYBWIokPKG+UqAS4WjfXXQEPwqGeoef0b5elB7dg
|
||||
6GjwOhJio4IDNzCCAzMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF
|
||||
BwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFBme/mBwOaT6f4yzzCBc4i/NPQBY
|
||||
MB8GA1UdIwQYMBaAFI8NE6L2Ln7RUGwzGDhdWY4jcpHKMDIGCCsGAQUFBwEBBCYw
|
||||
JDAiBggrBgEFBQcwAoYWaHR0cDovL2U4LmkubGVuY3Iub3JnLzCCATUGA1UdEQSC
|
||||
ASwwggEogg1haXIudW5peDcub3JnghJhaXJmb3JjZS51bml4Ny5vcmeCDWRldi51
|
||||
bml4Ny5vcmeCDWVkdS51bml4Ny5vcmeCEGVkdW1heC51bml4Ny5vcmeCDWdpdC51
|
||||
bml4Ny5vcmeCDWhhbS51bml4Ny5vcmeCDmhhc2gudW5peDcub3JnggxoZC51bml4
|
||||
Ny5vcmeCDm1haWwudW5peDcub3Jnggxtdy51bml4Ny5vcmeCDG14LnVuaXg3Lm9y
|
||||
Z4IOcGlraS51bml4Ny5vcmeCDHJtLnVuaXg3Lm9yZ4IQc3RvcmV4LnVuaXg3Lm9y
|
||||
Z4INdzEyLnVuaXg3Lm9yZ4INdzEzLnVuaXg3Lm9yZ4IOd2lraS51bml4Ny5vcmeC
|
||||
DXd3dy51bml4Ny5vcmcwEwYDVR0gBAwwCjAIBgZngQwBAgEwLQYDVR0fBCYwJDAi
|
||||
oCCgHoYcaHR0cDovL2U4LmMubGVuY3Iub3JnLzM1LmNybDCCAQsGCisGAQQB1nkC
|
||||
BAIEgfwEgfkA9wB1AGQRxGykEuyniRyiAi4AvKtPKAfUHjUnq+r+1QPJfc3wAAAB
|
||||
nFFT2U0AAAQDAEYwRAIgbuNiYUqwgxi9Oycm2D6h8sclWLcBXHtqFWpwJT3dwbgC
|
||||
IBBjMRcAmxZKE9PIgFqMvosPNQ7AAkbEfudVtqNkfwXJAH4Apcl4kl1XRheChw3Y
|
||||
iWYLXFVki30AQPLsB2hR0YhpGfcAAAGcUVPcHQAIAAAFADH4c7UEAwBHMEUCIQDz
|
||||
p9aYuw9jAZjxM8U3Qq7M4vFpp0GZDm80tpTdKYNjjwIgQ/e/lWg6uqQsjBytcaOG
|
||||
IVXPEyB0n8fflOf+Ekh51DUwCgYIKoZIzj0EAwMDZwAwZAIwRrEAdYBcRU46Pold
|
||||
w4VjUGnGsYEUqlsjrmn4awY01YGWknPaX5sTAI3hTuA32eOUAjA1dSANAAyO+icj
|
||||
1ZiPZUGFjaMdkEu6Y/Ge8aueAUItNj9eF0ahlgZEnSlhHrswoZo=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP
|
||||
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
|
||||
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
|
||||
Fw0yNzAzMTIyMzU5NTlaMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
|
||||
bmNyeXB0MQswCQYDVQQDEwJFODB2MBAGByqGSM49AgEGBSuBBAAiA2IABNFl8l7c
|
||||
S7QMApzSsvru6WyrOq44ofTUOTIzxULUzDMMNMchIJBwXOhiLxxxs0LXeb5GDcHb
|
||||
R6EToMffgSZjO9SNHfY9gjMy9vQr5/WWOrQTZxh7az6NSNnq3u2ubT6HTKOB+DCB
|
||||
9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB
|
||||
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFI8NE6L2Ln7RUGwzGDhdWY4j
|
||||
cpHKMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEB
|
||||
BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzATBgNVHSAE
|
||||
DDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5j
|
||||
ci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBnE0hGINKsCYWi0Xx1ygxD5qihEjZ0
|
||||
RI3tTZz1wuATH3ZwYPIp97kWEayanD1j0cDhIYzy4CkDo2jB8D5t0a6zZWzlr98d
|
||||
AQFNh8uKJkIHdLShy+nUyeZxc5bNeMp1Lu0gSzE4McqfmNMvIpeiwWSYO9w82Ob8
|
||||
otvXcO2JUYi3svHIWRm3+707DUbL51XMcY2iZdlCq4Wa9nbuk3WTU4gr6LY8MzVA
|
||||
aDQG2+4U3eJ6qUF10bBnR1uuVyDYs9RhrwucRVnfuDj29CMLTsplM5f5wSV5hUpm
|
||||
Uwp/vV7M4w4aGunt74koX71n4EdagCsL/Yk5+mAQU0+tue0JOfAV/R6t1k+Xk9s2
|
||||
HMQFeoxppfzAVC04FdG9M+AC2JWxmFSt6BCuh3CEey3fE52Qrj9YM75rtvIjsm/1
|
||||
Hl+u//Wqxnu1ZQ4jpa+VpuZiGOlWrqSP9eogdOhCGisnyewWJwRQOqK16wiGyZeR
|
||||
xs/Bekw65vwSIaVkBruPiTfMOo0Zh4gVa8/qJgMbJbyrwwG97z/PRgmLKCDl8z3d
|
||||
tA0Z7qq7fta0Gl24uyuB05dqI5J1LvAzKuWdIjT1tP8qCoxSE/xpix8hX2dt3h+/
|
||||
jujUgFPFZ0EVZ0xSyBNRF3MboGZnYXFUxpNjTWPKpagDHJQmqrAcDmWJnMsFY3jS
|
||||
u1igv3OefnWjSQ==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIOqwKQF1VWp3lSiIgD5E1ZNGXf/IlBLwEp8F+YooRiuGoAoGCCqGSM49
|
||||
AwEHoUQDQgAE2ZzcFAOjOZKpqt+qEZFEwvn0j5S4iw7N1c+nz3WAViKJDyhvlKgE
|
||||
uFo3110BD8KhnqHn9G+XpQe3YOho8DoSYg==
|
||||
-----END EC PRIVATE KEY-----
|
||||
@@ -0,0 +1,5 @@
|
||||
certpath: mbased.crt
|
||||
keypath: mbased.key
|
||||
runUser: root
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
module mproxy
|
||||
|
||||
go 1.25.7
|
||||
|
||||
require (
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/google/go-containerregistry v0.21.3
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jmoiron/sqlx v1.4.0
|
||||
github.com/mattn/go-sqlite3 v1.14.38
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.1.1
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.4
|
||||
helm.sh/helm/v4 v4.1.3
|
||||
sigs.k8s.io/yaml v1.6.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v29.3.0+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||
github.com/extism/go-sdk v1.7.1 // indirect
|
||||
github.com/fluxcd/cli-utils v0.37.2-flux.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gofrs/flock v0.13.0 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.18.4 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/moby/term v0.5.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect
|
||||
github.com/tetratelabs/wazero v1.11.0 // indirect
|
||||
github.com/vbatts/tar-split v0.12.2 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.47.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/term v0.39.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gotest.tools/v3 v3.5.2 // indirect
|
||||
k8s.io/api v0.35.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.35.1 // indirect
|
||||
k8s.io/apimachinery v0.35.1 // indirect
|
||||
k8s.io/cli-runtime v0.35.1 // indirect
|
||||
k8s.io/client-go v0.35.1 // indirect
|
||||
k8s.io/component-base v0.35.1 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
|
||||
k8s.io/kubectl v0.35.1 // indirect
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
|
||||
oras.land/oras-go/v2 v2.6.0 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.23.1 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.21.1 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.21.1 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 // indirect
|
||||
)
|
||||
@@ -0,0 +1,384 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
||||
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=
|
||||
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
|
||||
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=
|
||||
github.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v29.3.0+incompatible h1:z3iWveU7h19Pqx7alZES8j+IeFQZ1lhTwb2F+V9SVvk=
|
||||
github.com/docker/cli v29.3.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a h1:UwSIFv5g5lIvbGgtf3tVwC7Ky9rmMFBp0RMs+6f6YqE=
|
||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a/go.mod h1:C8DzXehI4zAbrdlbtOByKX6pfivJTBiV9Jjqv56Yd9Q=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
|
||||
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
|
||||
github.com/extism/go-sdk v1.7.1 h1:lWJos6uY+tRFdlIHR+SJjwFDApY7OypS/2nMhiVQ9Sw=
|
||||
github.com/extism/go-sdk v1.7.1/go.mod h1:IT+Xdg5AZM9hVtpFUA+uZCJMge/hbvshl8bwzLtFyKA=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fluxcd/cli-utils v0.37.2-flux.1 h1:tQ588ghtRN+E+kHq415FddfqA9v4brn/1WWgrP6rQR0=
|
||||
github.com/fluxcd/cli-utils v0.37.2-flux.1/go.mod h1:LcWSu1NYET8d8U7O326RhEm5JkQXCMK6ITu4G1CT02c=
|
||||
github.com/foxcpp/go-mockdns v1.2.0 h1:omK3OrHRD1IWJz1FuFBCFquhXslXoF17OvBS6JPzZF0=
|
||||
github.com/foxcpp/go-mockdns v1.2.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
|
||||
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
|
||||
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
|
||||
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
|
||||
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
||||
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-containerregistry v0.21.3 h1:Xr+yt3VvwOOn/5nJzd7UoOhwPGiPkYW0zWDLLUXqAi4=
|
||||
github.com/google/go-containerregistry v0.21.3/go.mod h1:D5ZrJF1e6dMzvInpBPuMCX0FxURz7GLq2rV3Us9aPkc=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII=
|
||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw=
|
||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca h1:T54Ema1DU8ngI+aef9ZhAhNGQhcRTrWxVeG07F+c/Rw=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.38 h1:tDUzL85kMvOrvpCt8P64SbGgVFtJB11GPi2AdmITgb4=
|
||||
github.com/mattn/go-sqlite3 v1.14.38/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
|
||||
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
|
||||
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=
|
||||
github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
|
||||
github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q=
|
||||
github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos=
|
||||
github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM=
|
||||
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho=
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U=
|
||||
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc=
|
||||
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ=
|
||||
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 h1:ZF+QBjOI+tILZjBaFj3HgFonKXUcwgJ4djLb6i42S3Q=
|
||||
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834/go.mod h1:m9ymHTgNSEjuxvw8E7WWe4Pl4hZQHXONY8wE6dMLaRk=
|
||||
github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA=
|
||||
github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU=
|
||||
github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=
|
||||
github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
||||
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/bridges/prometheus v0.65.0 h1:I/7S/yWobR3QHFLqHsJ8QOndoiFsj1VgHpQiq43KlUI=
|
||||
go.opentelemetry.io/contrib/bridges/prometheus v0.65.0/go.mod h1:jPF6gn3y1E+nozCAEQj3c6NZ8KY+tvAgSVfvoOJUFac=
|
||||
go.opentelemetry.io/contrib/exporters/autoexport v0.65.0 h1:2gApdml7SznX9szEKFjKjM4qGcGSvAybYLBY319XG3g=
|
||||
go.opentelemetry.io/contrib/exporters/autoexport v0.65.0/go.mod h1:0QqAGlbHXhmPYACG3n5hNzO5DnEqqtg4VcK5pr22RI0=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
|
||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0 h1:ZVg+kCXxd9LtAaQNKBxAvJ5NpMf7LpvEr4MIZqb0TMQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0/go.mod h1:hh0tMeZ75CCXrHd9OXRYxTlCAdxcXioWHFIpYw2rZu8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.16.0 h1:djrxvDxAe44mJUrKataUbOhCKhR3F8QCyWucO16hTQs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.16.0/go.mod h1:dt3nxpQEiSoKvfTVxp3TUg5fHPLhKtbcnN3Z1I1ePD0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.40.0 h1:NOyNnS19BF2SUDApbOKbDtWZ0IK7b8FJ2uAGdIWOGb0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.40.0/go.mod h1:VL6EgVikRLcJa9ftukrHu/ZkkhFBSo1lzvdBC9CF1ss=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.40.0 h1:9y5sHvAxWzft1WQ4BwqcvA+IFVUJ1Ya75mSAUnFEVwE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.40.0/go.mod h1:eQqT90eR3X5Dbs1g9YSM30RavwLF725Ris5/XSXWvqE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0 h1:wVZXIWjQSeSmMoxF74LzAnpVQOAFDo3pPji9Y4SOFKc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0/go.mod h1:khvBS2IggMFNwZK/6lEeHg/W57h/IX6J4URh57fuI40=
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.62.0 h1:krvC4JMfIOVdEuNPTtQ0ZjCiXrybhv+uOHMfHRmnvVo=
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.62.0/go.mod h1:fgOE6FM/swEnsVQCqCnbOfRV4tOnWPg7bVeo4izBuhQ=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.16.0 h1:ivlbaajBWJqhcCPniDqDJmRwj4lc6sRT+dCAVKNmxlQ=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.16.0/go.mod h1:u/G56dEKDDwXNCVLsbSrllB2o8pbtFLUC4HpR66r2dc=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0 h1:ZrPRak/kS4xI3AVXy8F7pipuDXmDsrO8Lg+yQjBLjw0=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0/go.mod h1:3y6kQCWztq6hyW8Z9YxQDDm0Je9AJoFar2G0yDcmhRk=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0 h1:MzfofMZN8ulNqobCmCAVbqVL5syHw+eB2qPRkCMA/fQ=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0/go.mod h1:E73G9UFtKRXrxhBsHtG00TB5WxX57lpsQzogDkqBTz8=
|
||||
go.opentelemetry.io/otel/log v0.16.0 h1:DeuBPqCi6pQwtCK0pO4fvMB5eBq6sNxEnuTs88pjsN4=
|
||||
go.opentelemetry.io/otel/log v0.16.0/go.mod h1:rWsmqNVTLIA8UnwYVOItjyEZDbKIkMxdQunsIhpUMes=
|
||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
||||
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
|
||||
go.opentelemetry.io/otel/sdk/log v0.16.0 h1:e/b4bdlQwC5fnGtG3dlXUrNOnP7c8YLVSpSfEBIkTnI=
|
||||
go.opentelemetry.io/otel/sdk/log v0.16.0/go.mod h1:JKfP3T6ycy7QEuv3Hj8oKDy7KItrEkus8XJE6EoSzw4=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
|
||||
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
helm.sh/helm/v4 v4.1.3 h1:Abfmb+oJUtxoaXDyB2Jhw1zRk3hT6aFfHta+AXb8Lno=
|
||||
helm.sh/helm/v4 v4.1.3/go.mod h1:5dSo8rRgn3OTkDAc/k0Ipw5/Q+BlqKIKZwa0XwSiINI=
|
||||
k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q=
|
||||
k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM=
|
||||
k8s.io/apiextensions-apiserver v0.35.1 h1:p5vvALkknlOcAqARwjS20kJffgzHqwyQRM8vHLwgU7w=
|
||||
k8s.io/apiextensions-apiserver v0.35.1/go.mod h1:2CN4fe1GZ3HMe4wBr25qXyJnJyZaquy4nNlNmb3R7AQ=
|
||||
k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU=
|
||||
k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
|
||||
k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE=
|
||||
k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw=
|
||||
k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM=
|
||||
k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA=
|
||||
k8s.io/component-base v0.35.1 h1:XgvpRf4srp037QWfGBLFsYMUQJkE5yMa94UsJU7pmcE=
|
||||
k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
|
||||
k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg=
|
||||
k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo=
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc=
|
||||
oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o=
|
||||
sigs.k8s.io/controller-runtime v0.23.1 h1:TjJSM80Nf43Mg21+RCy3J70aj/W6KyvDtOlpKf+PupE=
|
||||
sigs.k8s.io/controller-runtime v0.23.1/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/kustomize/api v0.21.1 h1:lzqbzvz2CSvsjIUZUBNFKtIMsEw7hVLJp0JeSIVmuJs=
|
||||
sigs.k8s.io/kustomize/api v0.21.1/go.mod h1:f3wkKByTrgpgltLgySCntrYoq5d3q7aaxveSagwTlwI=
|
||||
sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7fI=
|
||||
sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||
@@ -0,0 +1,3 @@
|
||||
*~
|
||||
istored
|
||||
istored.service
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# PROVIDE: mbased
|
||||
# REQUIRE: DAEMON
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="mbased"
|
||||
rcvar="mbased_enable"
|
||||
|
||||
pidfile="/home/ziggi/Projects/mproxy/tmp/run/mbased.pid"
|
||||
command="/usr/local/sbin/${name}"
|
||||
command_args="--asDaemon=true"
|
||||
procname="/usr/local/sbin/${name}"
|
||||
|
||||
load_rc_config ${name}
|
||||
|
||||
: ${mbased_enable:="NO"}
|
||||
|
||||
run_rc_command "$1"
|
||||
#EOF
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# PROVIDE: mbased
|
||||
# REQUIRE: DAEMON
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="mbased"
|
||||
rcvar="mbased_enable"
|
||||
|
||||
pidfile="@srv_rundir@/mbased.pid"
|
||||
command="@prefix@/sbin/${name}"
|
||||
command_args="--asDaemon=true"
|
||||
procname="@prefix@/sbin/${name}"
|
||||
|
||||
load_rc_config ${name}
|
||||
|
||||
: ${mbased_enable:="NO"}
|
||||
|
||||
run_rc_command "$1"
|
||||
#EOF
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=mbased
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/home/ziggi/Projects/mproxy/tmp/run/mbased.pid
|
||||
ExecStart=/usr/local/sbin/mbased --asDaemon=true --port=443
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=mbased
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=@srv_rundir@/mbased.pid
|
||||
ExecStart=@prefix@/sbin/mbased --asDaemon=true --port=443
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Executable
+541
@@ -0,0 +1,541 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2024-06-19.01; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# 'make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
tab=' '
|
||||
nl='
|
||||
'
|
||||
IFS=" $tab$nl"
|
||||
|
||||
# Set DOITPROG to "echo" to test this script.
|
||||
|
||||
doit=${DOITPROG-}
|
||||
doit_exec=${doit:-exec}
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
# Create dirs (including intermediate dirs) using mode 755.
|
||||
# This is like GNU 'install' as of coreutils 8.32 (2020).
|
||||
mkdir_umask=22
|
||||
|
||||
backupsuffix=
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
is_target_a_directory=possibly
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-p pass -p to $cpprog.
|
||||
-s $stripprog installed files.
|
||||
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
|
||||
By default, rm is invoked with -f; when overridden with RMPROG,
|
||||
it's up to you to specify -f if you want it.
|
||||
|
||||
If -S is not specified, no backups are attempted.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
GNU Automake home page: <https://www.gnu.org/software/automake/>.
|
||||
General help using GNU software: <https://www.gnu.org/gethelp/>."
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-p) cpprog="$cpprog -p";;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-S) backupsuffix="$2"
|
||||
shift;;
|
||||
|
||||
-t)
|
||||
is_target_a_directory=always
|
||||
dst_arg=$2
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) is_target_a_directory=never;;
|
||||
|
||||
--version) echo "$0 (GNU Automake) $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# We allow the use of options -d and -T together, by making -d
|
||||
# take the precedence; this is for compatibility with GNU install.
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
if test -n "$dst_arg"; then
|
||||
echo "$0: target directory not allowed when installing a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call 'install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||
if test ! -d "$dst_arg"; then
|
||||
echo "$0: $dst_arg: Is not a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
# Don't chown directories that already exist.
|
||||
if test $dstdir_status = 0; then
|
||||
chowncmd=""
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename.
|
||||
if test -d "$dst"; then
|
||||
if test "$is_target_a_directory" = never; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dstbase=`basename "$src"`
|
||||
case $dst in
|
||||
*/) dst=$dst$dstbase;;
|
||||
*) dst=$dst/$dstbase;;
|
||||
esac
|
||||
dstdir_status=0
|
||||
else
|
||||
dstdir=`dirname "$dst"`
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
case $dstdir in
|
||||
*/) dstdirslash=$dstdir;;
|
||||
*) dstdirslash=$dstdir/;;
|
||||
esac
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
# The $RANDOM variable is not portable (e.g., dash). Use it
|
||||
# here however when possible just to lower collision chance.
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
|
||||
trap '
|
||||
ret=$?
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
|
||||
exit $ret
|
||||
' 0
|
||||
|
||||
# Because "mkdir -p" follows existing symlinks and we likely work
|
||||
# directly in world-writable /tmp, make sure that the '$tmpdir'
|
||||
# directory is successfully created first before we actually test
|
||||
# 'mkdir -p'.
|
||||
if (umask $mkdir_umask &&
|
||||
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibility with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
test_tmpdir="$tmpdir/a"
|
||||
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=${dstdirslash}_inst.$$_
|
||||
rmtmp=${dstdirslash}_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask &&
|
||||
{ test -z "$stripcmd" || {
|
||||
# Create $dsttmp read-write so that cp doesn't create it read-only,
|
||||
# which would cause strip to fail.
|
||||
if test -z "$doit"; then
|
||||
: >"$dsttmp" # No need to fork-exec 'touch'.
|
||||
else
|
||||
$doit touch "$dsttmp"
|
||||
fi
|
||||
}
|
||||
} &&
|
||||
$doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
set +f &&
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# If $backupsuffix is set, and the file being installed
|
||||
# already exists, attempt a backup. Don't worry if it fails,
|
||||
# e.g., if mv doesn't support -f.
|
||||
if test -n "$backupsuffix" && test -f "$dst"; then
|
||||
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
|
||||
fi
|
||||
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
|
||||
|
||||
dist_man1_MANS = \
|
||||
mproxyctl.1 \
|
||||
mproxyctl-accounts.1 \
|
||||
mproxyctl-accounts-create.1 \
|
||||
mproxyctl-accounts-delete.1 \
|
||||
mproxyctl-accounts-get.1 \
|
||||
mproxyctl-accounts-list.1 \
|
||||
mproxyctl-accounts-update.1 \
|
||||
mproxyctl-grants.1 \
|
||||
mproxyctl-grants-create.1 \
|
||||
mproxyctl-grants-delete.1 \
|
||||
mproxyctl-grants-get.1 \
|
||||
mproxyctl-grants-list.1 \
|
||||
mproxyctl-grants-update.1
|
||||
|
||||
|
||||
dist_man8_MANS = \
|
||||
mproxyd.8
|
||||
|
||||
man:
|
||||
$(GO) run makeman-mstorectl.go
|
||||
$(GO) run makeman-mstored.go
|
||||
|
||||
EXTRA_DIST = \
|
||||
makeman-mstorectl.go \
|
||||
makeman-mstored.go
|
||||
@@ -0,0 +1,585 @@
|
||||
# Makefile.in generated by automake 1.17 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
am__rm_f = rm -f $(am__rm_f_notfound)
|
||||
am__rm_rf = rm -rf $(am__rm_f_notfound)
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = mans
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
depcomp =
|
||||
am__maybe_remake_depfiles =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
{ test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
|
||||
}
|
||||
man1dir = $(mandir)/man1
|
||||
am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man8dir)"
|
||||
man8dir = $(mandir)/man8
|
||||
NROFF = nroff
|
||||
MANS = $(dist_man1_MANS) $(dist_man8_MANS)
|
||||
am__extra_recursive_targets = docs-recursive
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
am__DIST_COMMON = $(dist_man1_MANS) $(dist_man8_MANS) \
|
||||
$(srcdir)/Makefile.in
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BASENAME = @BASENAME@
|
||||
CP = @CP@
|
||||
CPIO = @CPIO@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DBUILDPACKAGE = @DBUILDPACKAGE@
|
||||
DEFS = @DEFS@
|
||||
DPKGSOURCE = @DPKGSOURCE@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
ETAGS = @ETAGS@
|
||||
FIND = @FIND@
|
||||
GO = @GO@
|
||||
HAVE_GO = @HAVE_GO@
|
||||
HELM = @HELM@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PODMAN = @PODMAN@
|
||||
ROOT_GROUP = @ROOT_GROUP@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SORT = @SORT@
|
||||
STRIP = @STRIP@
|
||||
SUDO = @SUDO@
|
||||
SWAG = @SWAG@
|
||||
UNIQ = @UNIQ@
|
||||
VERSION = @VERSION@
|
||||
XARGS = @XARGS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__rm_f_notfound = @am__rm_f_notfound@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
am__xargs_n = @am__xargs_n@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
srv_confdir = @srv_confdir@
|
||||
srv_datadir = @srv_datadir@
|
||||
srv_devel_mode = @srv_devel_mode@
|
||||
srv_libdir = @srv_libdir@
|
||||
srv_logdir = @srv_logdir@
|
||||
srv_rundir = @srv_rundir@
|
||||
srv_sharedir = @srv_sharedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
|
||||
dist_man1_MANS = \
|
||||
mproxyctl.1 \
|
||||
mproxyctl-accounts.1 \
|
||||
mproxyctl-accounts-create.1 \
|
||||
mproxyctl-accounts-delete.1 \
|
||||
mproxyctl-accounts-get.1 \
|
||||
mproxyctl-accounts-list.1 \
|
||||
mproxyctl-accounts-update.1 \
|
||||
mproxyctl-grants.1 \
|
||||
mproxyctl-grants-create.1 \
|
||||
mproxyctl-grants-delete.1 \
|
||||
mproxyctl-grants-get.1 \
|
||||
mproxyctl-grants-list.1 \
|
||||
mproxyctl-grants-update.1
|
||||
|
||||
dist_man8_MANS = \
|
||||
mproxyd.8
|
||||
|
||||
EXTRA_DIST = \
|
||||
makeman-mstorectl.go \
|
||||
makeman-mstored.go
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign mans/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign mans/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-man1: $(dist_man1_MANS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list1='$(dist_man1_MANS)'; \
|
||||
list2=''; \
|
||||
test -n "$(man1dir)" \
|
||||
&& test -n "`echo $$list1$$list2`" \
|
||||
|| exit 0; \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
|
||||
{ for i in $$list1; do echo "$$i"; done; \
|
||||
if test -n "$$list2"; then \
|
||||
for i in $$list2; do echo "$$i"; done \
|
||||
| sed -n '/\.1[a-z]*$$/p'; \
|
||||
fi; \
|
||||
} | while read p; do \
|
||||
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; echo "$$p"; \
|
||||
done | \
|
||||
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
|
||||
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
|
||||
sed 'N;N;s,\n, ,g' | { \
|
||||
list=; while read file base inst; do \
|
||||
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
|
||||
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
|
||||
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
|
||||
fi; \
|
||||
done; \
|
||||
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
|
||||
done; }
|
||||
|
||||
uninstall-man1:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(dist_man1_MANS)'; test -n "$(man1dir)" || exit 0; \
|
||||
files=`{ for i in $$list; do echo "$$i"; done; \
|
||||
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
|
||||
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
|
||||
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
|
||||
install-man8: $(dist_man8_MANS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list1='$(dist_man8_MANS)'; \
|
||||
list2=''; \
|
||||
test -n "$(man8dir)" \
|
||||
&& test -n "`echo $$list1$$list2`" \
|
||||
|| exit 0; \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
|
||||
{ for i in $$list1; do echo "$$i"; done; \
|
||||
if test -n "$$list2"; then \
|
||||
for i in $$list2; do echo "$$i"; done \
|
||||
| sed -n '/\.8[a-z]*$$/p'; \
|
||||
fi; \
|
||||
} | while read p; do \
|
||||
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; echo "$$p"; \
|
||||
done | \
|
||||
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
|
||||
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
|
||||
sed 'N;N;s,\n, ,g' | { \
|
||||
list=; while read file base inst; do \
|
||||
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
|
||||
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
|
||||
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
|
||||
fi; \
|
||||
done; \
|
||||
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
|
||||
done; }
|
||||
|
||||
uninstall-man8:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(dist_man8_MANS)'; test -n "$(man8dir)" || exit 0; \
|
||||
files=`{ for i in $$list; do echo "$$i"; done; \
|
||||
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
|
||||
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
|
||||
dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
|
||||
docs-local:
|
||||
tags TAGS:
|
||||
|
||||
ctags CTAGS:
|
||||
|
||||
cscope cscopelist:
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(MANS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man8dir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-$(am__rm_f) $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
docs: docs-am
|
||||
|
||||
docs-am: docs-local
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-man
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man: install-man1 install-man8
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-man
|
||||
|
||||
uninstall-man: uninstall-man1 uninstall-man8
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
|
||||
ctags-am distclean distclean-generic distdir docs-am \
|
||||
docs-local dvi dvi-am html html-am info info-am install \
|
||||
install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-man1 install-man8 install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
|
||||
pdf-am ps ps-am tags-am uninstall uninstall-am uninstall-man \
|
||||
uninstall-man1 uninstall-man8
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
man:
|
||||
$(GO) run makeman-mstorectl.go
|
||||
$(GO) run makeman-mstored.go
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
|
||||
# Tell GNU make to disable its built-in pattern rules.
|
||||
%:: %,v
|
||||
%:: RCS/%,v
|
||||
%:: RCS/%
|
||||
%:: s.%
|
||||
%:: SCCS/s.%
|
||||
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra/doc"
|
||||
|
||||
"mproxy/cmd/mproxyctl/util"
|
||||
)
|
||||
|
||||
func run() error {
|
||||
var err error
|
||||
os.Args[0] = "mproxyctl"
|
||||
util := util.NewUtil()
|
||||
err = util.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := util.GetRooCmd()
|
||||
now := time.Now()
|
||||
header := &doc.GenManHeader{
|
||||
Title: "mproxyctl",
|
||||
Section: "1",
|
||||
Manual: "User commands",
|
||||
Source: "mproxyctl command",
|
||||
Date: &now,
|
||||
}
|
||||
opts := doc.GenManTreeOptions{
|
||||
Header: header,
|
||||
Path: "./",
|
||||
CommandSeparator: "-",
|
||||
}
|
||||
err = doc.GenManTreeFromOpts(cmd, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra/doc"
|
||||
|
||||
"mproxy/cmd/mproxyd/starter"
|
||||
)
|
||||
|
||||
func run() error {
|
||||
var err error
|
||||
os.Args[0] = "mproxyd"
|
||||
util := starter.NewStarter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := util.GetCmd()
|
||||
now := time.Now()
|
||||
header := &doc.GenManHeader{
|
||||
Title: "mproxyd",
|
||||
Section: "8",
|
||||
Manual: "User commands",
|
||||
Source: "mproxyd command",
|
||||
Date: &now,
|
||||
}
|
||||
opts := doc.GenManTreeOptions{
|
||||
Header: header,
|
||||
Path: "./",
|
||||
CommandSeparator: "-",
|
||||
}
|
||||
err = doc.GenManTreeFromOpts(cmd, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
.nh
|
||||
.TH "mproxyctl" "1" "May 2026" "mproxyctl command" "User commands"
|
||||
|
||||
.SH NAME
|
||||
mproxyctl -
|
||||
Operation with artefacts: files, images, service accounts and grants
|
||||
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBmproxyctl [flags]\fP
|
||||
|
||||
|
||||
.SH DESCRIPTION
|
||||
Operation with artefacts: files, images, service accounts and grants
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
\fB-h\fP, \fB--help\fP[=false]
|
||||
help for mproxyctl
|
||||
|
||||
|
||||
.SH HISTORY
|
||||
26-May-2026 Auto generated by spf13/cobra
|
||||
@@ -0,0 +1,31 @@
|
||||
.nh
|
||||
.TH "mproxyd" "8" "May 2026" "mproxyd command" "User commands"
|
||||
|
||||
.SH NAME
|
||||
mproxyd -
|
||||
Artifact storage service
|
||||
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBmproxyd [flags]\fP
|
||||
|
||||
|
||||
.SH DESCRIPTION
|
||||
Artifact storage service
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
\fB-D\fP, \fB--asDaemon\fP[=true]
|
||||
Run service as daemon
|
||||
|
||||
.PP
|
||||
\fB-h\fP, \fB--help\fP[=false]
|
||||
help for mproxyd
|
||||
|
||||
.PP
|
||||
\fB-P\fP, \fB--port\fP=1025
|
||||
Service port
|
||||
|
||||
|
||||
.SH HISTORY
|
||||
26-May-2026 Auto generated by spf13/cobra
|
||||
@@ -0,0 +1,236 @@
|
||||
#! /bin/sh
|
||||
# Common wrapper for a few potentially missing GNU and other programs.
|
||||
|
||||
scriptversion=2024-06-07.14; # UTC
|
||||
|
||||
# shellcheck disable=SC2006,SC2268 # we must support pre-POSIX shells
|
||||
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
|
||||
--is-lightweight)
|
||||
# Used by our autoconf macros to check whether the available missing
|
||||
# script is modern enough.
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--run)
|
||||
# Back-compat with the calling convention used by older automake.
|
||||
shift
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||
to PROGRAM being missing or too old.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal autoconf autogen autoheader autom4te automake autoreconf
|
||||
bison flex help2man lex makeinfo perl yacc
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||
'g' are ignored when checking the name.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
GNU Automake home page: <https://www.gnu.org/software/automake/>.
|
||||
General help using GNU software: <https://www.gnu.org/gethelp/>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing (GNU Automake) $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: unknown '$1' option"
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Run the given program, remember its exit status.
|
||||
"$@"; st=$?
|
||||
|
||||
# If it succeeded, we are done.
|
||||
test $st -eq 0 && exit 0
|
||||
|
||||
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||
# passed; such an option is passed most likely to detect whether the
|
||||
# program is present and works.
|
||||
case $2 in --version|--help) exit $st;; esac
|
||||
|
||||
# Exit code 63 means version mismatch. This often happens when the user
|
||||
# tries to use an ancient version of a tool on a file that requires a
|
||||
# minimum version.
|
||||
if test $st -eq 63; then
|
||||
msg="probably too old"
|
||||
elif test $st -eq 127; then
|
||||
# Program was missing.
|
||||
msg="missing on your system"
|
||||
else
|
||||
# Program was found and executed, but failed. Give up.
|
||||
exit $st
|
||||
fi
|
||||
|
||||
perl_URL=https://www.perl.org/
|
||||
flex_URL=https://github.com/westes/flex
|
||||
gnu_software_URL=https://www.gnu.org/software
|
||||
|
||||
program_details ()
|
||||
{
|
||||
case $1 in
|
||||
aclocal|automake|autoreconf)
|
||||
echo "The '$1' program is part of the GNU Automake package:"
|
||||
echo "<$gnu_software_URL/automake>"
|
||||
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/autoconf>"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
autoconf|autom4te|autoheader)
|
||||
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||
echo "<$gnu_software_URL/autoconf/>"
|
||||
echo "It also requires GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
*)
|
||||
:
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice ()
|
||||
{
|
||||
# Normalize program name to check for.
|
||||
normalized_program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
printf '%s\n' "'$1' is $msg."
|
||||
|
||||
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||
autoheader_deps="'acconfig.h'"
|
||||
automake_deps="'Makefile.am'"
|
||||
aclocal_deps="'acinclude.m4'"
|
||||
case $normalized_program in
|
||||
aclocal*)
|
||||
echo "You should only need it if you modified $aclocal_deps or"
|
||||
echo "$configure_deps."
|
||||
;;
|
||||
autoconf*)
|
||||
echo "You should only need it if you modified $configure_deps."
|
||||
;;
|
||||
autogen*)
|
||||
echo "You should only need it if you modified a '.def' or '.tpl' file."
|
||||
echo "You may want to install the GNU AutoGen package:"
|
||||
echo "<$gnu_software_URL/autogen/>"
|
||||
;;
|
||||
autoheader*)
|
||||
echo "You should only need it if you modified $autoheader_deps or"
|
||||
echo "$configure_deps."
|
||||
;;
|
||||
automake*)
|
||||
echo "You should only need it if you modified $automake_deps or"
|
||||
echo "$configure_deps."
|
||||
;;
|
||||
autom4te*)
|
||||
echo "You might have modified some maintainer files that require"
|
||||
echo "the 'autom4te' program to be rebuilt."
|
||||
;;
|
||||
autoreconf*)
|
||||
echo "You should only need it if you modified $aclocal_deps or"
|
||||
echo "$automake_deps or $autoheader_deps or $automake_deps or"
|
||||
echo "$configure_deps."
|
||||
;;
|
||||
bison*|yacc*)
|
||||
echo "You should only need it if you modified a '.y' file."
|
||||
echo "You may want to install the GNU Bison package:"
|
||||
echo "<$gnu_software_URL/bison/>"
|
||||
;;
|
||||
help2man*)
|
||||
echo "You should only need it if you modified a dependency" \
|
||||
"of a man page."
|
||||
echo "You may want to install the GNU Help2man package:"
|
||||
echo "<$gnu_software_URL/help2man/>"
|
||||
;;
|
||||
lex*|flex*)
|
||||
echo "You should only need it if you modified a '.l' file."
|
||||
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||
echo "<$flex_URL>"
|
||||
;;
|
||||
makeinfo*)
|
||||
echo "You should only need it if you modified a '.texi' file, or"
|
||||
echo "any other file indirectly affecting the aspect of the manual."
|
||||
echo "You might want to install the Texinfo package:"
|
||||
echo "<$gnu_software_URL/texinfo/>"
|
||||
echo "The spurious makeinfo call might also be the consequence of"
|
||||
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||
echo "want to install GNU make:"
|
||||
echo "<$gnu_software_URL/make/>"
|
||||
;;
|
||||
perl*)
|
||||
echo "You should only need it to run GNU Autoconf, GNU Automake, "
|
||||
echo " assorted other tools, or if you modified a Perl source file."
|
||||
echo "You may want to install the Perl 5 language interpreter:"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
*)
|
||||
echo "You might have modified some files without having the proper"
|
||||
echo "tools for further handling them. Check the 'README' file, it"
|
||||
echo "often tells you about the needed prerequisites for installing"
|
||||
echo "this package. You may also peek at any GNU archive site, in"
|
||||
echo "case some other package contains this missing '$1' program."
|
||||
;;
|
||||
esac
|
||||
program_details "$normalized_program"
|
||||
}
|
||||
|
||||
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||
-e '2,$s/^/ /' >&2
|
||||
|
||||
# Propagate the correct exit status (expected to be 127 for a program
|
||||
# not found, 63 for a program that failed due to version mismatch).
|
||||
exit $st
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package auxhttp
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func EncodeBasicAuth(username, password string) string {
|
||||
auth := username + ":" + password
|
||||
return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
|
||||
}
|
||||
|
||||
func ParseBasicAuth(basicFields string) (string, string, error) {
|
||||
var err error
|
||||
var username string
|
||||
var password string
|
||||
if basicFields == "" {
|
||||
err := fmt.Errorf("Empty auth field")
|
||||
return username, password, err
|
||||
}
|
||||
authFields := strings.SplitN(basicFields, " ", 2)
|
||||
if len(authFields) < 2 {
|
||||
err = fmt.Errorf("Cannot split auth field: %s", basicFields)
|
||||
return username, password, err
|
||||
}
|
||||
authType := strings.TrimSpace(authFields[0])
|
||||
if strings.ToLower(authType) != strings.ToLower("Basic") {
|
||||
err = fmt.Errorf("Not basic auth type")
|
||||
return username, password, err
|
||||
}
|
||||
authPairEncoded := authFields[1]
|
||||
pairEncoded, err := base64.StdEncoding.DecodeString(authPairEncoded)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Cannon decode auth pair")
|
||||
return username, password, err
|
||||
}
|
||||
authPair := strings.SplitN(string(pairEncoded), ":", 2)
|
||||
if len(authPair) != 2 {
|
||||
err = fmt.Errorf("Wrong auth pair")
|
||||
return username, password, err
|
||||
}
|
||||
username = authPair[0]
|
||||
password = authPair[1]
|
||||
return username, password, err
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package auxhttp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ParseOCIContentRange(ref string) (int64, int64, error) {
|
||||
var start, end int64
|
||||
var err error
|
||||
|
||||
startstop := strings.TrimSpace(ref)
|
||||
tmp := strings.SplitN(startstop, "-", 2)
|
||||
if len(tmp) != 2 {
|
||||
err = fmt.Errorf("Wrong Content-Range definition, strange range def %v", startstop)
|
||||
return start, end, err
|
||||
}
|
||||
startstr := tmp[0]
|
||||
endstr := tmp[1]
|
||||
|
||||
start, err = strconv.ParseInt(startstr, 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Wrong Content-Range definition, strange start %s", startstr)
|
||||
return start, end, err
|
||||
}
|
||||
end, err = strconv.ParseInt(endstr, 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Wrong Content-Range definition, strange end %s", endstr)
|
||||
return start, end, err
|
||||
}
|
||||
return start, end, err
|
||||
}
|
||||
|
||||
func ParseContentRange(ref string) (int64, int64, int64, error) {
|
||||
var start, end, total int64
|
||||
var err error
|
||||
|
||||
const bytesUnit = "bytes"
|
||||
|
||||
tmp := strings.SplitN(ref, " ", 2)
|
||||
if len(tmp) != 2 {
|
||||
err := fmt.Errorf("Wrong Content-Range definition, len is only %d", len(tmp))
|
||||
return start, end, total, err
|
||||
}
|
||||
unit := strings.ToLower(tmp[0])
|
||||
if unit != bytesUnit {
|
||||
err = fmt.Errorf("Wrong Content-Range definition, strange length def %s", unit)
|
||||
return start, end, total, err
|
||||
}
|
||||
ranger := strings.TrimSpace(tmp[1])
|
||||
|
||||
tmp = strings.Split(ranger, "/")
|
||||
if len(tmp) != 2 {
|
||||
err = fmt.Errorf("Wrong Content-Range definition, dont found total")
|
||||
return start, end, total, err
|
||||
}
|
||||
totalstr := tmp[1]
|
||||
if totalstr == "*" {
|
||||
total = 0
|
||||
} else {
|
||||
total, err = strconv.ParseInt(totalstr, 10, 64)
|
||||
if err != nil {
|
||||
return start, end, total, err
|
||||
}
|
||||
}
|
||||
startstop := tmp[0]
|
||||
tmp = strings.SplitN(startstop, "-", 2)
|
||||
if len(tmp) != 2 {
|
||||
err = fmt.Errorf("Wrong Content-Range definition, strange range def %v", startstop)
|
||||
return start, end, total, err
|
||||
}
|
||||
startstr := tmp[0]
|
||||
endstr := tmp[1]
|
||||
|
||||
start, err = strconv.ParseInt(startstr, 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Wrong Content-Range definition, strange start %s", startstr)
|
||||
return start, end, total, err
|
||||
}
|
||||
end, err = strconv.ParseInt(endstr, 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Wrong Content-Range definition, strange end %s", endstr)
|
||||
return start, end, total, err
|
||||
}
|
||||
return start, end, total, err
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxpwd
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var rnd *rand.Rand
|
||||
|
||||
const (
|
||||
sha256Prefix = "sha256pwd"
|
||||
sha512Prefix = "sha512pwd"
|
||||
saltSize = 16
|
||||
)
|
||||
|
||||
func init() {
|
||||
src := rand.NewSource(time.Now().UnixNano())
|
||||
rnd = rand.New(src)
|
||||
}
|
||||
|
||||
func MakeSHA256Hash(passwd []byte) string {
|
||||
var res string
|
||||
salt := hex.EncodeToString(randomBytes(saltSize))
|
||||
passwdString := hex.EncodeToString(passwd)
|
||||
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
||||
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(passwdString))
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
|
||||
res = fmt.Sprintf("%s:%s:%s", sha256Prefix, salt, checksum)
|
||||
return res
|
||||
}
|
||||
|
||||
func MakeSHA512Hash(passwd []byte) string {
|
||||
var res string
|
||||
salt := hex.EncodeToString(randomBytes(saltSize))
|
||||
passwdString := hex.EncodeToString(passwd)
|
||||
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
||||
|
||||
hasher := sha512.New()
|
||||
hasher.Write([]byte(passwdString))
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
|
||||
res = fmt.Sprintf("%s:%s:%s", sha512Prefix, salt, checksum)
|
||||
return res
|
||||
}
|
||||
|
||||
func PasswordMatch(passwd []byte, hash string) bool {
|
||||
hashComponents := strings.Split(hash, ":")
|
||||
if len(hashComponents) != 3 {
|
||||
return false
|
||||
}
|
||||
method := hashComponents[0]
|
||||
salt := hashComponents[1]
|
||||
controlChecksum := hashComponents[2]
|
||||
|
||||
switch method {
|
||||
case sha256Prefix:
|
||||
passwdString := hex.EncodeToString(passwd)
|
||||
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(passwdString))
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
if checksum != controlChecksum {
|
||||
return false
|
||||
}
|
||||
case sha512Prefix:
|
||||
passwdString := hex.EncodeToString(passwd)
|
||||
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
||||
hasher := sha512.New()
|
||||
hasher.Write([]byte(passwdString))
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
if checksum != controlChecksum {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func randomString(n int) string {
|
||||
const letters = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
arr := make([]byte, n)
|
||||
lettersArrayLen := len(letters)
|
||||
for i := range arr {
|
||||
arr[i] = letters[rnd.Intn(lettersArrayLen)]
|
||||
}
|
||||
return string(arr)
|
||||
}
|
||||
|
||||
func randomBytes(n int) []byte {
|
||||
arr := make([]byte, n)
|
||||
for i := range arr {
|
||||
arr[i] = byte(rnd.Intn(256) & 0xFF)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxpwd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPasswd256(t *testing.T) {
|
||||
password := []byte("123456789")
|
||||
wrongPasswd := []byte("qwerty")
|
||||
|
||||
hash := MakeSHA256Hash(password)
|
||||
fmt.Printf("%s\n", hash)
|
||||
{
|
||||
match := PasswordMatch(password, hash)
|
||||
require.Equal(t, true, match)
|
||||
}
|
||||
{
|
||||
match := PasswordMatch(wrongPasswd, hash)
|
||||
require.NotEqual(t, true, match)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswd512(t *testing.T) {
|
||||
password := []byte("123456781")
|
||||
wrongPasswd := []byte("qwerty")
|
||||
|
||||
hash := MakeSHA512Hash(password)
|
||||
fmt.Printf("%s\n", hash)
|
||||
{
|
||||
match := PasswordMatch(password, hash)
|
||||
require.Equal(t, true, match)
|
||||
}
|
||||
{
|
||||
match := PasswordMatch(wrongPasswd, hash)
|
||||
require.NotEqual(t, true, match)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxtool
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Clean only overbase elements of dir path if possible
|
||||
func CleanDirs(basedir, datadir string) {
|
||||
separator := string(os.PathSeparator)
|
||||
|
||||
basedir = filepath.Clean(separator + basedir)
|
||||
datadir = filepath.Clean(separator + datadir)
|
||||
|
||||
items := strings.Split(datadir, separator)
|
||||
for i := len(items); i > 0; i-- {
|
||||
p := filepath.Join(items[0:i]...)
|
||||
p = filepath.Clean(separator + p)
|
||||
if p == basedir {
|
||||
break
|
||||
}
|
||||
fileInfo, err := os.Stat(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if fileInfo.IsDir() {
|
||||
err = os.Remove(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package auxtool
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func FileExists(name string) bool {
|
||||
fileStat, err := os.Stat(name)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if fileStat.IsDir() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func DirExists(name string) bool {
|
||||
fileStat, err := os.Stat(name)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if fileStat == nil {
|
||||
return false
|
||||
}
|
||||
return fileStat.IsDir()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*
|
||||
*
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
|
||||
package auxtool
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func RandomString(n int) string {
|
||||
const letters = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
arr := make([]byte, n)
|
||||
for i := range arr {
|
||||
arr[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return string(arr)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxtool
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
func MakeTmpFilename(prefix string) string {
|
||||
randBytes := make([]byte, 6)
|
||||
rand.Read(randBytes)
|
||||
suffix := hex.EncodeToString(randBytes)
|
||||
return fmt.Sprintf("%s.tmp.%s", prefix, suffix)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxtool
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func TimeNow() string {
|
||||
return time.Now().Format(time.RFC3339)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxutar
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Archive(srcdir, dstpath string) error {
|
||||
var err error
|
||||
srcdir = filepath.Clean(srcdir)
|
||||
dstpath = filepath.Clean(dstpath)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dstpath), 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tarFile, err := os.OpenFile(dstpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tarFile.Close()
|
||||
|
||||
tarWriter := tar.NewWriter(tarFile)
|
||||
defer tarWriter.Close()
|
||||
|
||||
walker := func(filename string, fileInfo os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !fileInfo.Mode().IsRegular() {
|
||||
return nil
|
||||
}
|
||||
header, err := tar.FileInfoHeader(fileInfo, fileInfo.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Name = strings.TrimPrefix(filename, filepath.Clean(srcdir))
|
||||
header.Name = strings.TrimPrefix(header.Name, string(filepath.Separator))
|
||||
err = tarWriter.WriteHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wrapfunc := func() error {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(tarWriter, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
err = wrapfunc()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err = filepath.Walk(srcdir, walker)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func Unarchive(filename, dstdir string) error {
|
||||
var err error
|
||||
err = os.MkdirAll(dstdir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.OpenFile(filename, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
tarReader := tar.NewReader(file)
|
||||
for {
|
||||
header, err := tarReader.Next()
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
return nil
|
||||
case err != nil:
|
||||
return err
|
||||
case header == nil:
|
||||
continue
|
||||
}
|
||||
target := filepath.Join(dstdir, header.Name)
|
||||
target = filepath.Clean(target)
|
||||
|
||||
fileInfo := header.FileInfo()
|
||||
switch header.Typeflag {
|
||||
case tar.TypeDir:
|
||||
_, err := os.Stat(target)
|
||||
if os.IsNotExist(err) {
|
||||
err = nil
|
||||
err := os.MkdirAll(target, fileInfo.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case tar.TypeReg:
|
||||
wrapfunc := func() error {
|
||||
dir := filepath.Dir(target)
|
||||
_, err := os.Stat(dir)
|
||||
if os.IsNotExist(err) {
|
||||
err := os.MkdirAll(dir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, fileInfo.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(file, tarReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
err = wrapfunc()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = os.Chtimes(target, time.Now(), fileInfo.ModTime())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = file.Chmod(fileInfo.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxuuid
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const ZeroUUID string = "00000000-0000-0000-0000-000000000000"
|
||||
|
||||
func NewUUID() string {
|
||||
return uuid.New().String()
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxx509
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CreateSelfSignedCert(subject string, dnsNames ...string) ([]byte, []byte, error) {
|
||||
var err error
|
||||
certPem := make([]byte, 0)
|
||||
keyPem := make([]byte, 0)
|
||||
|
||||
now := time.Now()
|
||||
|
||||
const yearsAfter int = 10
|
||||
const keySize int = 2048
|
||||
|
||||
key, err := rsa.GenerateKey(rand.Reader, keySize)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Can't create a private key: %v", err)
|
||||
return certPem, keyPem, err
|
||||
|
||||
}
|
||||
keyPemBlock := pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(key),
|
||||
}
|
||||
keyPem = pem.EncodeToMemory(&keyPemBlock)
|
||||
|
||||
names := make([]string, 0)
|
||||
names = append(names, subject)
|
||||
names = append(names, dnsNames...)
|
||||
tml := x509.Certificate{
|
||||
SerialNumber: big.NewInt(now.Unix()),
|
||||
NotBefore: now,
|
||||
NotAfter: now.AddDate(yearsAfter, 0, 0),
|
||||
Subject: pkix.Name{
|
||||
CommonName: subject,
|
||||
},
|
||||
DNSNames: names,
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
certBytes, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
|
||||
if err != nil {
|
||||
return certPem, keyPem, fmt.Errorf("Can't create a certificate: %v", err)
|
||||
|
||||
}
|
||||
certPemBlock := pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: certBytes,
|
||||
}
|
||||
certPem = pem.EncodeToMemory(&certPemBlock)
|
||||
if err != nil {
|
||||
return certPem, keyPem, err
|
||||
}
|
||||
return certPem, keyPem, err
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package auxx509
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCert(t *testing.T) {
|
||||
caCert, caKey, err := CreateSelfSignedCert("test1")
|
||||
require.NoError(t, err)
|
||||
fmt.Println(string(caCert))
|
||||
fmt.Println(string(caKey))
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*
|
||||
* This work is published and licensed under a Creative Commons
|
||||
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
|
||||
*
|
||||
* Distribution of this work is permitted, but commercial use and
|
||||
* modifications are strictly prohibited.
|
||||
*/
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"mproxy/pkg/auxhttp"
|
||||
"mproxy/pkg/descr"
|
||||
)
|
||||
|
||||
func (cli *Client) FileInfo(ctx context.Context, fileuri string) (bool, *descr.File, error) {
|
||||
var exists bool
|
||||
var err error
|
||||
file := &descr.File{}
|
||||
fileuri, username, password, err := repackServiceURI(fileuri)
|
||||
if err != nil {
|
||||
return exists, file, err
|
||||
}
|
||||
fileuri, err = convertFileURI(fileuri)
|
||||
if err != nil {
|
||||
return exists, file, err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodHead, fileuri, nil)
|
||||
if err != nil {
|
||||
return exists, file, err
|
||||
}
|
||||
if username != "" && password != "" {
|
||||
basic := auxhttp.EncodeBasicAuth(username, password)
|
||||
req.Header.Add("Authorization", basic)
|
||||
}
|
||||
client := makeHTTPClient(cli.skipTLSVerify)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return exists, file, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
file.Collection = resp.Header.Get("Content-Collection")
|
||||
file.Name = resp.Header.Get("Content-Name")
|
||||
contentSize := resp.Header.Get("Content-Size")
|
||||
size, err := strconv.ParseInt(contentSize, 10, 64)
|
||||
if err != nil {
|
||||
return exists, file, err
|
||||
}
|
||||
file.Size = size
|
||||
file.Type = resp.Header.Get("Content-Type")
|
||||
file.Checksum = resp.Header.Get("Content-Digest")
|
||||
exists = true
|
||||
}
|
||||
return exists, file, err
|
||||
}
|
||||
|
||||
func (cli *Client) PutFile(ctx context.Context, filename, fileuri string) error {
|
||||
var err error
|
||||
fileuri, username, password, err := repackServiceURI(fileuri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileuri, err = convertFileURI(fileuri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fileuri, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileinfo, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filesize := fileinfo.Size()
|
||||
|
||||
req.ContentLength = filesize
|
||||
req.Header.Set("Content-Type", "application/octet-stream")
|
||||
req.Header.Set("Content-Size", strconv.FormatInt(filesize, 10))
|
||||
if username != "" && password != "" {
|
||||
basic := auxhttp.EncodeBasicAuth(username, password)
|
||||
req.Header.Add("Authorization", basic)
|
||||
}
|
||||
client := makeHTTPClient(cli.skipTLSVerify)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (cli *Client) GetFile(ctx context.Context, fileuri, filename string) (int64, error) {
|
||||
var err error
|
||||
var size int64
|
||||
|
||||
fileuri, username, password, err := repackServiceURI(fileuri)
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
fileuri, err = convertFileURI(fileuri)
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fileuri, nil)
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
if username != "" && password != "" {
|
||||
basic := auxhttp.EncodeBasicAuth(username, password)
|
||||
req.Header.Add("Authorization", basic)
|
||||
}
|
||||
client := makeHTTPClient(cli.skipTLSVerify)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
contentLength := resp.Header.Get("Content-Length")
|
||||
if contentLength == "" {
|
||||
err = fmt.Errorf("Empty Content-Length received")
|
||||
return size, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
|
||||
return size, err
|
||||
}
|
||||
declSize, err := strconv.ParseInt(contentLength, 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Wrong Content-Length value: %v", err)
|
||||
return size, err
|
||||
}
|
||||
dirname := filepath.Dir(filename)
|
||||
err = os.MkdirAll(dirname, 0750)
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0640)
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
size, err = io.Copy(file, resp.Body)
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
if size != declSize {
|
||||
err := fmt.Errorf("Mismatch Content-Length and recorded filesize")
|
||||
return size, err
|
||||
}
|
||||
return size, err
|
||||
}
|
||||
|
||||
func (cli *Client) DeleteFile(ctx context.Context, fileuri string) error {
|
||||
var err error
|
||||
|
||||
fileuri, username, password, err := repackServiceURI(fileuri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileuri, err = convertFileURI(fileuri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fileuri, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if username != "" && password != "" {
|
||||
basic := auxhttp.EncodeBasicAuth(username, password)
|
||||
req.Header.Add("Authorization", basic)
|
||||
}
|
||||
client := makeHTTPClient(cli.skipTLSVerify)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (cli *Client) ListFiles(ctx context.Context, catalogURI, usePathAs string) ([]descr.File, error) {
|
||||
var err error
|
||||
res := make([]descr.File, 0)
|
||||
|
||||
catalogURI, username, password, err := repackServiceURI(catalogURI)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
catalogURI, err = convertFilesURI(catalogURI)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
// Add values
|
||||
values := url.Values{}
|
||||
if usePathAs != "" {
|
||||
values.Add("pathAs", string(usePathAs))
|
||||
}
|
||||
encodedValues := values.Encode()
|
||||
if encodedValues != "" {
|
||||
catalogURI = catalogURI + "?" + encodedValues
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, catalogURI, nil)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if username != "" && password != "" {
|
||||
basic := auxhttp.EncodeBasicAuth(username, password)
|
||||
req.Header.Add("Authorization", basic)
|
||||
}
|
||||
client := makeHTTPClient(cli.skipTLSVerify)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
contentLength := resp.Header.Get("Content-Length")
|
||||
if contentLength == "" {
|
||||
err = fmt.Errorf("Empty Content-Length received")
|
||||
return res, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
|
||||
return res, err
|
||||
}
|
||||
declSize, err := strconv.ParseInt(contentLength, 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Wrong Content-Length value: %v", err)
|
||||
return res, err
|
||||
}
|
||||
respBuffer := bytes.NewBuffer(nil)
|
||||
size, err := io.Copy(respBuffer, resp.Body)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
respBytes := respBuffer.Bytes()
|
||||
if size != declSize {
|
||||
err := fmt.Errorf("Mismatch Content-Length and recorded filesize")
|
||||
return res, err
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &res)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (cli *Client) ListCollections(ctx context.Context, catalogURI, usePathAs string) ([]string, error) {
|
||||
var err error
|
||||
res := make([]string, 0)
|
||||
|
||||
catalogURI, username, password, err := repackServiceURI(catalogURI)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
catalogURI, err = convertCollectionsURI(catalogURI)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Add values
|
||||
values := url.Values{}
|
||||
if usePathAs != "" {
|
||||
values.Add("pathAs", string(usePathAs))
|
||||
}
|
||||
encodedValues := values.Encode()
|
||||
if encodedValues != "" {
|
||||
catalogURI = catalogURI + "?" + encodedValues
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, catalogURI, nil)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if username != "" && password != "" {
|
||||
basic := auxhttp.EncodeBasicAuth(username, password)
|
||||
req.Header.Add("Authorization", basic)
|
||||
}
|
||||
client := makeHTTPClient(cli.skipTLSVerify)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
contentLength := resp.Header.Get("Content-Length")
|
||||
if contentLength == "" {
|
||||
err = fmt.Errorf("Empty Content-Length received")
|
||||
return res, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
|
||||
return res, err
|
||||
}
|
||||
declSize, err := strconv.ParseInt(contentLength, 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Wrong Content-Length value: %v", err)
|
||||
return res, err
|
||||
}
|
||||
respBuffer := bytes.NewBuffer(nil)
|
||||
size, err := io.Copy(respBuffer, resp.Body)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
respBytes := respBuffer.Bytes()
|
||||
if size != declSize {
|
||||
err := fmt.Errorf("Mismatch Content-Length and recorded filesize")
|
||||
return res, err
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &res)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (cli *Client) DeleteCollection(ctx context.Context, catalogURI, usePathAs string, dryRun bool) ([]descr.File, error) {
|
||||
var err error
|
||||
res := make([]descr.File, 0)
|
||||
|
||||
catalogURI, username, password, err := repackServiceURI(catalogURI)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
catalogURI, err = convertCollectionURI(catalogURI)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
// Add values
|
||||
values := url.Values{}
|
||||
if usePathAs != "" {
|
||||
values.Add("pathAs", string(usePathAs))
|
||||
}
|
||||
if dryRun {
|
||||
values.Add("dryRun", "true")
|
||||
}
|
||||
encodedValues := values.Encode()
|
||||
if encodedValues != "" {
|
||||
catalogURI = catalogURI + "?" + encodedValues
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, catalogURI, nil)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if username != "" && password != "" {
|
||||
basic := auxhttp.EncodeBasicAuth(username, password)
|
||||
req.Header.Add("Authorization", basic)
|
||||
}
|
||||
client := makeHTTPClient(cli.skipTLSVerify)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
contentLength := resp.Header.Get("Content-Length")
|
||||
if contentLength == "" {
|
||||
err = fmt.Errorf("Empty Content-Length received")
|
||||
return res, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
|
||||
return res, err
|
||||
}
|
||||
declSize, err := strconv.ParseInt(contentLength, 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Wrong Content-Length value: %v", err)
|
||||
return res, err
|
||||
}
|
||||
respBuffer := bytes.NewBuffer(nil)
|
||||
size, err := io.Copy(respBuffer, resp.Body)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
respBytes := respBuffer.Bytes()
|
||||
if size != declSize {
|
||||
err := fmt.Errorf("Mismatch Content-Length and recorded filesize")
|
||||
return res, err
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &res)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package servcli
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
httpClient *http.Client
|
||||
userAgent string
|
||||
}
|
||||
|
||||
func NewClient(transport http.RoundTripper, mwFuncs ...MiddlewareFunc) *Client {
|
||||
if transport == nil {
|
||||
transport = NewDefaultTransport()
|
||||
}
|
||||
for _, mwFunc := range mwFuncs {
|
||||
transport = mwFunc(transport)
|
||||
}
|
||||
httpClient := &http.Client{
|
||||
Transport: transport,
|
||||
}
|
||||
|
||||
return &Client{
|
||||
httpClient: httpClient,
|
||||
userAgent: "ociClient/1.0",
|
||||
}
|
||||
}
|
||||
|
||||
func (cli *Client) SetTransport(transport http.RoundTripper) {
|
||||
cli.httpClient.Transport = transport
|
||||
}
|
||||
|
||||
type MiddlewareFunc func(next http.RoundTripper) http.RoundTripper
|
||||
|
||||
func (cli *Client) UseMiddleware(mwFunc MiddlewareFunc) {
|
||||
cli.httpClient.Transport = mwFunc(cli.httpClient.Transport)
|
||||
}
|
||||
|
||||
// BasicAuthMiddleware
|
||||
func NewBasicAuthMiddleware(user, pass string) MiddlewareFunc {
|
||||
return func(next http.RoundTripper) http.RoundTripper {
|
||||
return newBasicAuthMW(next, user, pass)
|
||||
}
|
||||
}
|
||||
|
||||
type BasicAuthMW struct {
|
||||
user, pass string
|
||||
next http.RoundTripper
|
||||
}
|
||||
|
||||
func newBasicAuthMW(next http.RoundTripper, user, pass string) *BasicAuthMW {
|
||||
return &BasicAuthMW{
|
||||
user: user,
|
||||
pass: pass,
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
|
||||
func (tran BasicAuthMW) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if tran.user != "" && tran.pass != "" {
|
||||
pair := base64.StdEncoding.EncodeToString([]byte(tran.user + ":" + tran.pass))
|
||||
req.Header.Set("Authorization", "Basic "+pair)
|
||||
}
|
||||
return tran.next.RoundTrip(req)
|
||||
}
|
||||
|
||||
// BearerAuthMiddleware
|
||||
func NewBearerAuthMiddleware(token string) MiddlewareFunc {
|
||||
return func(next http.RoundTripper) http.RoundTripper {
|
||||
return newBearerAuthMW(next, token)
|
||||
}
|
||||
}
|
||||
|
||||
type BearerAuthMW struct {
|
||||
token string
|
||||
next http.RoundTripper
|
||||
}
|
||||
|
||||
func newBearerAuthMW(next http.RoundTripper, token string) *BearerAuthMW {
|
||||
return &BearerAuthMW{
|
||||
token: token,
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
|
||||
func (tran BearerAuthMW) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
req.Header.Set("Authorization", "Bearer "+tran.token)
|
||||
return tran.next.RoundTrip(req)
|
||||
}
|
||||
|
||||
// DefaultTransport
|
||||
type DefaultTransport struct {
|
||||
transport http.RoundTripper
|
||||
}
|
||||
|
||||
func NewDefaultTransport() *DefaultTransport {
|
||||
return &DefaultTransport{
|
||||
transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wrap *DefaultTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return wrap.transport.RoundTrip(req)
|
||||
}
|
||||
|
||||
// ExampleMiddleware
|
||||
func NewExampleMiddleware() MiddlewareFunc {
|
||||
return func(next http.RoundTripper) http.RoundTripper {
|
||||
return newExampleTransport(next)
|
||||
}
|
||||
}
|
||||
|
||||
type ExampleTransport struct {
|
||||
next http.RoundTripper
|
||||
}
|
||||
|
||||
func newExampleTransport(next http.RoundTripper) *ExampleTransport {
|
||||
return &ExampleTransport{
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
|
||||
func (tran ExampleTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return tran.next.RoundTrip(req)
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*/
|
||||
package servcli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (cli *Client) doHTTPCall(ctx context.Context, host, obj, oper string, req []byte) ([]byte, error) {
|
||||
var err error
|
||||
var res []byte
|
||||
|
||||
reader := bytes.NewReader(req)
|
||||
ref, err := NewReferer(host, obj, oper)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, ref.Point(), reader)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
httpReq.Header.Set("User-Agent", cli.userAgent)
|
||||
httpReq.Header.Set("Accept", "*/*")
|
||||
httpResp, err := cli.httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
defer httpResp.Body.Close()
|
||||
if httpResp.StatusCode != http.StatusOK {
|
||||
err := fmt.Errorf("Unexpected response code: %s", httpResp.Status)
|
||||
return res, err
|
||||
}
|
||||
contentLength := httpResp.Header.Get("Content-Length")
|
||||
if contentLength == "" {
|
||||
err := fmt.Errorf("Content-Length header is missing")
|
||||
return res, err
|
||||
}
|
||||
blobSize, err := strconv.ParseInt(contentLength, 10, 64)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
recSize, err := io.Copy(buffer, httpResp.Body)
|
||||
if blobSize != recSize {
|
||||
err := fmt.Errorf("Mismatch declared and actual body size, %d and %d", blobSize, recSize)
|
||||
return res, err
|
||||
}
|
||||
res = buffer.Bytes()
|
||||
return res, err
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user