Compare commits
	
		
			9 Commits
		
	
	
		
			decrease-d
			...
			test-build
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9ca9af0ab3 | ||
| 
						 | 
					0f5c7a81a2 | ||
| 
						 | 
					0f80b14869 | ||
| 
						 | 
					c594257c4f | ||
| 
						 | 
					bd6c0a0bc6 | ||
| 
						 | 
					04c79984c0 | ||
| 
						 | 
					534834680b | ||
| 
						 | 
					a6737c1871 | ||
| 
						 | 
					07e156dd3f | 
							
								
								
									
										46
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								.drone.yml
									
									
									
									
									
								
							@@ -1,46 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
kind: pipeline
 | 
			
		||||
type: kubernetes
 | 
			
		||||
name: Containeraztion latest
 | 
			
		||||
steps:
 | 
			
		||||
- name: Docker build
 | 
			
		||||
  resources:
 | 
			
		||||
    limits:
 | 
			
		||||
      cpu: 100
 | 
			
		||||
      memory: 2048MiB
 | 
			
		||||
  when:
 | 
			
		||||
   branch:
 | 
			
		||||
     - main
 | 
			
		||||
  privileged: true
 | 
			
		||||
  settings:
 | 
			
		||||
    registry: git.badhouseplants.net
 | 
			
		||||
    username: allanger
 | 
			
		||||
    password: 
 | 
			
		||||
      from_secret: GITEA_TOKEN
 | 
			
		||||
    repo: git.badhouseplants.net/badhouseplants/clever-install
 | 
			
		||||
    tags: latest
 | 
			
		||||
    platforms: 
 | 
			
		||||
      - linux/arm64
 | 
			
		||||
      - linux/amd64
 | 
			
		||||
 | 
			
		||||
steps:
 | 
			
		||||
- name: Docker build
 | 
			
		||||
  image: thegeeklab/drone-docker-buildx
 | 
			
		||||
  trigger:
 | 
			
		||||
    event:
 | 
			
		||||
      - tag
 | 
			
		||||
  resources:
 | 
			
		||||
    limits:
 | 
			
		||||
      cpu: 100
 | 
			
		||||
      memory: 2048MiB
 | 
			
		||||
  privileged: true
 | 
			
		||||
  settings:
 | 
			
		||||
    registry: git.badhouseplants.net
 | 
			
		||||
    username: allanger
 | 
			
		||||
    password: 
 | 
			
		||||
      from_secret: GITEA_TOKEN
 | 
			
		||||
    repo: git.badhouseplants.net/badhouseplants/clever-install
 | 
			
		||||
    tags: latest
 | 
			
		||||
    platforms: 
 | 
			
		||||
      - linux/arm64
 | 
			
		||||
      - linux/amd64
 | 
			
		||||
							
								
								
									
										48
									
								
								.github/workflows/build-container.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/build-container.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
---
 | 
			
		||||
name: "Build container"
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  containerization:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    permissions:
 | 
			
		||||
      packages: write
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        include:
 | 
			
		||||
          - arch: amd64
 | 
			
		||||
          - arch: arm64
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout
 | 
			
		||||
        uses: actions/checkout@v3
 | 
			
		||||
      
 | 
			
		||||
      - name: Install buildah
 | 
			
		||||
        run: sudo apt update && sudo apt install -y podman buildah qemu-user-static
 | 
			
		||||
 | 
			
		||||
      - name: Set version tag (only if triggered by pushing a tag)
 | 
			
		||||
        if: startsWith(github.ref, 'refs/tags/v')
 | 
			
		||||
        run: echo "TAG=${GITHUB_REF##*/}" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Set latest tag (only if triggered by pushing to the main branch)
 | 
			
		||||
        if: github.ref == 'main'
 | 
			
		||||
        run: echo "TAG=latest" >> $GITHUB_ENV
 | 
			
		||||
      
 | 
			
		||||
      - name: Set action link variable
 | 
			
		||||
        run: echo "LINK=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Login in gchr registry
 | 
			
		||||
        run: buildah login --username ${{ github.repository_owner }} --password ${{ secrets.GITHUB_TOKEN }} ghcr.io
 | 
			
		||||
 | 
			
		||||
      - name: Build an image
 | 
			
		||||
        run: |
 | 
			
		||||
          buildah bud -t ghcr.io/${{ github.repository }}:${{ github.sha }}-${{ matrix.arch }} \
 | 
			
		||||
            --label action_id=${{ github.action }} \
 | 
			
		||||
            --label action_link=${{ env.LINK }} \
 | 
			
		||||
            --label actor=${{ github.actor }} \
 | 
			
		||||
            --label sha=${{ github.sha }} \
 | 
			
		||||
            --label ref=${{ github.ref }} \
 | 
			
		||||
            .
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/workflows/build-version.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build-version.yaml
									
									
									
									
										vendored
									
									
								
							@@ -50,7 +50,7 @@ jobs:
 | 
			
		||||
        uses: actions/download-artifact@v3
 | 
			
		||||
 | 
			
		||||
      - name: Set version variable
 | 
			
		||||
        run: echo "CLIN_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
 | 
			
		||||
        run: echo "VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Rename release to avoid name conflict
 | 
			
		||||
        run: ./scripts/rename_releases.sh
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								.github/workflows/container-stable.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										53
									
								
								.github/workflows/container-stable.yaml
									
									
									
									
										vendored
									
									
								
							@@ -1,53 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
name: "Stable container"
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  containerization:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    permissions:
 | 
			
		||||
      packages: write
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout
 | 
			
		||||
        uses: actions/checkout@v3
 | 
			
		||||
 | 
			
		||||
      - name: Set action link variable
 | 
			
		||||
        run: echo "LINK=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Set up QEMU
 | 
			
		||||
        uses: docker/setup-qemu-action@master
 | 
			
		||||
        with:
 | 
			
		||||
          platforms: all
 | 
			
		||||
 | 
			
		||||
      - name: Set up Docker Buildx
 | 
			
		||||
        id: buildx
 | 
			
		||||
        uses: docker/setup-buildx-action@master
 | 
			
		||||
 | 
			
		||||
      - name: Login to GitHub Container Registry
 | 
			
		||||
        uses: docker/login-action@v2
 | 
			
		||||
        with:
 | 
			
		||||
          registry: ghcr.io
 | 
			
		||||
          username: ${{ github.repository_owner }}
 | 
			
		||||
          password: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
 | 
			
		||||
      - name: Build
 | 
			
		||||
        uses: docker/build-push-action@v3
 | 
			
		||||
        with:
 | 
			
		||||
          builder: ${{ steps.buildx.outputs.name }}
 | 
			
		||||
          context: .
 | 
			
		||||
          file: ./Dockerfile
 | 
			
		||||
          platforms: linux/amd64,linux/arm64
 | 
			
		||||
          push: true
 | 
			
		||||
          tags: |
 | 
			
		||||
            ghcr.io/${{ github.repository }}:stable
 | 
			
		||||
            ghcr.io/${{ github.repository }}:latest
 | 
			
		||||
          labels: |
 | 
			
		||||
            action_id=${{ github.action }}
 | 
			
		||||
            action_link=${{ env.LINK }}
 | 
			
		||||
            actor=${{ github.actor }}
 | 
			
		||||
            sha=${{ github.sha }}
 | 
			
		||||
            ref=${{ github.ref }}
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/workflows/container-version.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/container-version.yaml
									
									
									
									
										vendored
									
									
								
							@@ -47,6 +47,7 @@ jobs:
 | 
			
		||||
          push: true
 | 
			
		||||
          tags: |
 | 
			
		||||
            ghcr.io/${{ github.repository }}:${{ env.TAG }}
 | 
			
		||||
            ghcr.io/${{ github.repository }}:stable
 | 
			
		||||
          labels: |
 | 
			
		||||
            action_id=${{ github.action }}
 | 
			
		||||
            action_link=${{ env.LINK }}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										691
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										691
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "dudo"
 | 
			
		||||
version = "0.1.1"
 | 
			
		||||
version = "0.2.1"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
@@ -11,3 +11,8 @@ log = "0.4.17"
 | 
			
		||||
http = "0.2.8"
 | 
			
		||||
serde = { version = "1.0.126", features = ["derive"] }
 | 
			
		||||
reqwest = { version = "0.11", features = ["json", "blocking", "rustls"] }
 | 
			
		||||
serde_yaml = "0.9"
 | 
			
		||||
 | 
			
		||||
[dev-dependencies]
 | 
			
		||||
tempfile = "3.4.0"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								Containerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Containerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
FROM registry.hub.docker.com/library/rust:1.70.0-slim-bookworm as builder
 | 
			
		||||
WORKDIR /src
 | 
			
		||||
RUN apt-get update &&\
 | 
			
		||||
		apt-get install -y libssl-dev gcc musl pkg-config
 | 
			
		||||
COPY ./ .
 | 
			
		||||
RUN rustup default nightly && rustup update
 | 
			
		||||
RUN cargo build --release --jobs 2 -Z sparse-registry
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FROM debian:stable
 | 
			
		||||
COPY --from=builder /src/target/release/dudo /bin/dudo
 | 
			
		||||
RUN apt-get update -y &&\
 | 
			
		||||
		apt-get install openssl ca-certificates -y &&\
 | 
			
		||||
		apt-get clean -y
 | 
			
		||||
RUN chmod +x /bin/dudo
 | 
			
		||||
WORKDIR /workdir
 | 
			
		||||
ENTRYPOINT ["/bin/dudo"]
 | 
			
		||||
							
								
								
									
										16
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -1,16 +0,0 @@
 | 
			
		||||
FROM rust:1.67.1-slim-buster as builder
 | 
			
		||||
WORKDIR /src
 | 
			
		||||
RUN apt-get update &&\
 | 
			
		||||
		apt-get install -y libssl-dev gcc musl pkg-config
 | 
			
		||||
COPY ./ .
 | 
			
		||||
RUN cargo build --release
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FROM debian:stable
 | 
			
		||||
COPY --from=builder /src/target/release/dudo /bin/dudo
 | 
			
		||||
RUN apt-get update &&\
 | 
			
		||||
		apt-get install openssl ca-certificates &&\
 | 
			
		||||
		apt-get clean
 | 
			
		||||
RUN chmod +x /bin/dudo
 | 
			
		||||
WORKDIR /workdir
 | 
			
		||||
ENTRYPOINT ["/bin/dudo"]
 | 
			
		||||
							
								
								
									
										73
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								README.md
									
									
									
									
									
								
							@@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
# What's it about?
 | 
			
		||||
It's just a tool to make downloading binaries for different platforms easier. 
 | 
			
		||||
 | 
			
		||||
## For example
 | 
			
		||||
If you want to build a docker image, but you want to make it available on different platforms. But your tool needs other tools as dependencies, e.g. `helm`.
 | 
			
		||||
To install helm on Alpine you need to use curl, wget, or something. You need to choose a version, an operating system, and an architecture. For me, it was obvious that you must be able to use `uname -m`...
 | 
			
		||||
@@ -32,15 +33,15 @@ Prebuilt binaries exist for **Linux x86_64** and **MacOS arm64** and **x86_64**
 | 
			
		||||
 | 
			
		||||
Don't forget to add the binary to $PATH
 | 
			
		||||
```
 | 
			
		||||
$ curl https://raw.githubusercontent.com/allanger/clever-install/main/scripts/download_dudo.sh | bash
 | 
			
		||||
$ dudo -h
 | 
			
		||||
$ curl https://raw.githubusercontent.com/allanger/dumb-downloader/main/scripts/download_dudo.sh | bash
 | 
			
		||||
$ dudo --help
 | 
			
		||||
```
 | 
			
		||||
### Docker
 | 
			
		||||
 | 
			
		||||
You can use the `latest` or a `tagged` docker image
 | 
			
		||||
```
 | 
			
		||||
$ docker pull ghcr.io/allanger/clever-install:latest
 | 
			
		||||
$ docker run ghcr.io/allanger/clever-install:latest dudo -h
 | 
			
		||||
$ docker pull ghcr.io/allanger/dumb-downloader:latest
 | 
			
		||||
$ docker run ghcr.io/allanger/dumb-downloader:latest dudo -h
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Build from source
 | 
			
		||||
@@ -48,7 +49,67 @@ $ docker run ghcr.io/allanger/clever-install:latest dudo -h
 | 
			
		||||
```
 | 
			
		||||
$ cargo build --release
 | 
			
		||||
``` 
 | 
			
		||||
2. Run `gum help`
 | 
			
		||||
2. Run `dudo --help`
 | 
			
		||||
 | 
			
		||||
# How to use?
 | 
			
		||||
To be done
 | 
			
		||||
## Custom configurations
 | 
			
		||||
 | 
			
		||||
In case the default config is not doing the trick for you, you can pass a custom configuration, for example, you need to download a package "package-linux-amd64_x86_64_intel_v1.0.3" and this kind of name for an architecture is not supported by the `dudo`, then you can create a config file like 
 | 
			
		||||
```yaml
 | 
			
		||||
# config-example.yaml
 | 
			
		||||
---
 | 
			
		||||
---
 | 
			
		||||
os:
 | 
			
		||||
  macos:
 | 
			
		||||
    - macos
 | 
			
		||||
    - darwin
 | 
			
		||||
    - mac
 | 
			
		||||
    - apple
 | 
			
		||||
  linux:
 | 
			
		||||
    - linux
 | 
			
		||||
  windows:
 | 
			
		||||
    - windows
 | 
			
		||||
  freebsd:
 | 
			
		||||
    - freebsd
 | 
			
		||||
arch:
 | 
			
		||||
  x86_64:
 | 
			
		||||
    - x86_64
 | 
			
		||||
    - amd64
 | 
			
		||||
    - amd
 | 
			
		||||
    - intel
 | 
			
		||||
    - amd64_x86_64_intel
 | 
			
		||||
  aarch64:
 | 
			
		||||
    - aarch64
 | 
			
		||||
    - arm64
 | 
			
		||||
    - m1
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
And execute `dudo -l "package-{{ os }}-{{ arch }}-{{ version}}" -p v1.0.3 -d /tmp/package` and dudo will download the package to the `/tmp/package` then, 
 | 
			
		||||
 | 
			
		||||
## Dockerfile
 | 
			
		||||
 | 
			
		||||
The initial intetion for developing this was to use it for writing multi-architecture Dockerfiles for my another projects. I needed to download `helm` and `helmfile` for `arm64` and `amd64`. And I couldn't come up with good simple script for settings environment variables that would point to the the correct url, because `uname -m` wasn't giving me results that I would need. I was thinkg about writing a script to create some kind of map for different architectures, but then I thought that is was already not the first time I was having that problem and I decided to come up with a tool. And here is example, how one could use it in a `Dockerfile`
 | 
			
		||||
 | 
			
		||||
```DOCKERFILE
 | 
			
		||||
ARG BASE_VERSION=latest
 | 
			
		||||
FROM ghcr.io/allanger/dumb-downloader as builder
 | 
			
		||||
RUN apt-get update -y && apt-get install tar -y
 | 
			
		||||
ARG HELM_VERSION=v3.10.3
 | 
			
		||||
ARG HELMFILE_VERSION=0.151.0
 | 
			
		||||
ENV RUST_LOG=info
 | 
			
		||||
RUN dudo -l "https://github.com/helmfile/helmfile/releases/download/v{{ version }}/helmfile_{{ version }}_{{ os }}_{{ arch }}.tar.gz" -i /tmp/helmfile.tar.gz -p $HELMFILE_VERSION
 | 
			
		||||
RUN dudo -l "https://get.helm.sh/helm-{{ version }}-{{ os }}-{{ arch }}.tar.gz" -i /tmp/helm.tar.gz -p $HELM_VERSION
 | 
			
		||||
RUN tar -xf /tmp/helm.tar.gz  -C /tmp && rm -f /tmp/helm.tar.gz 
 | 
			
		||||
RUN tar -xf /tmp/helmfile.tar.gz  -C /tmp && rm -f /tmp/helmfile.tar.gz 
 | 
			
		||||
RUN mkdir /out && for bin in `find /tmp | grep helm`; do cp $bin /out/; done
 | 
			
		||||
RUN chmod +x /out/helm
 | 
			
		||||
RUN chmod +x /out/helmfile
 | 
			
		||||
 | 
			
		||||
FROM ghcr.io/allanger/check-da-helm-base:${BASE_VERSION} 
 | 
			
		||||
COPY --from=builder /out/ /usr/bin
 | 
			
		||||
RUN apk update --no-cache && apk add --no-cache jq bash
 | 
			
		||||
ENTRYPOINT ["cdh"]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In the builder it is downloading dependencies that are needed in my final docker image.
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
FROM debian:stable
 | 
			
		||||
COPY ./target/release/dudo /bin/dudo
 | 
			
		||||
RUN apt-get update &&\
 | 
			
		||||
                apt-get install openssl ca-certificates &&\
 | 
			
		||||
                apt-get clean
 | 
			
		||||
RUN chmod +x /bin/dudo
 | 
			
		||||
WORKDIR /workdir
 | 
			
		||||
ENTRYPOINT ["/bin/dudo"]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								example/config.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								example/config.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
---
 | 
			
		||||
os:
 | 
			
		||||
  macos:
 | 
			
		||||
    - macos
 | 
			
		||||
    - darwin
 | 
			
		||||
    - mac
 | 
			
		||||
    - apple
 | 
			
		||||
  linux:
 | 
			
		||||
    - linux
 | 
			
		||||
  windows:
 | 
			
		||||
    - windows
 | 
			
		||||
  freebsd:
 | 
			
		||||
    - freebsd
 | 
			
		||||
arch:
 | 
			
		||||
  x86_64:
 | 
			
		||||
    - x86_64
 | 
			
		||||
    - amd64
 | 
			
		||||
    - amd
 | 
			
		||||
    - intel
 | 
			
		||||
  aarch64:
 | 
			
		||||
    - aarch64
 | 
			
		||||
    - arm64
 | 
			
		||||
    - m1
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
echo 'renaming dudo to dudo-$VERSION-$SYSTEM format'
 | 
			
		||||
mkdir -p release
 | 
			
		||||
echo "version - $CLIN_VERSION"
 | 
			
		||||
echo "version - $VERSION"
 | 
			
		||||
for BUILD in build*; do
 | 
			
		||||
  SYSTEM=$(echo $BUILD | sed -e 's/build-//g')
 | 
			
		||||
  echo "system - $SYSTEM"
 | 
			
		||||
  cp $BUILD/dudo release/dudo-$CLIN_VERSION-$SYSTEM
 | 
			
		||||
  cp $BUILD/dudo release/dudo-$VERSION-$SYSTEM
 | 
			
		||||
done
 | 
			
		||||
ls release
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										243
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -5,64 +5,251 @@ use log::{error, info};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
use std::{
 | 
			
		||||
    collections::HashMap,
 | 
			
		||||
    env::consts::{ARCH, OS},
 | 
			
		||||
    fs::File,
 | 
			
		||||
    io,
 | 
			
		||||
    fmt::Display,
 | 
			
		||||
    fs::{File, OpenOptions},
 | 
			
		||||
    io::{self},
 | 
			
		||||
    process::exit,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type Result<T> = std::result::Result<T, DudoError>;
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
enum DudoError {
 | 
			
		||||
    IoError(io::Error),
 | 
			
		||||
    SerdeYamlError(serde_yaml::Error),
 | 
			
		||||
}
 | 
			
		||||
impl From<io::Error> for DudoError {
 | 
			
		||||
    fn from(error: io::Error) -> Self {
 | 
			
		||||
        DudoError::IoError(error)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<serde_yaml::Error> for DudoError {
 | 
			
		||||
    fn from(error: serde_yaml::Error) -> Self {
 | 
			
		||||
        DudoError::SerdeYamlError(error)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Display for DudoError {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            DudoError::SerdeYamlError(err) => write!(f, "{}", err),
 | 
			
		||||
            DudoError::IoError(err) => write!(f, "{}", err),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CONFIG: &str = "
 | 
			
		||||
---
 | 
			
		||||
os:
 | 
			
		||||
  macos:
 | 
			
		||||
    - macos
 | 
			
		||||
    - darwin
 | 
			
		||||
    - mac
 | 
			
		||||
    - apple
 | 
			
		||||
  linux:
 | 
			
		||||
    - linux
 | 
			
		||||
  windows:
 | 
			
		||||
    - windows
 | 
			
		||||
  freebsd:
 | 
			
		||||
    - freebsd
 | 
			
		||||
arch:
 | 
			
		||||
  x86_64:
 | 
			
		||||
    - x86_64
 | 
			
		||||
    - amd64
 | 
			
		||||
    - amd
 | 
			
		||||
    - intel
 | 
			
		||||
  aarch64:
 | 
			
		||||
    - aarch64
 | 
			
		||||
    - arm64
 | 
			
		||||
    - m1
 | 
			
		||||
";
 | 
			
		||||
 | 
			
		||||
/// Maybe not that clever, but at least not dumb. Download binaries for defferent architectures easier
 | 
			
		||||
#[derive(Parser)]
 | 
			
		||||
#[clap(author = "allanger <allanger@zohomail.com>", version, about, long_about = None, arg_required_else_help(true))]
 | 
			
		||||
struct Args {
 | 
			
		||||
    /// A templated link for downloading
 | 
			
		||||
    #[clap(short, long, env = "CLIN_LINK")]
 | 
			
		||||
    #[clap(short, long, env = "DUDO_LINK_TEMPLATE")]
 | 
			
		||||
    link_template: String,
 | 
			
		||||
    /// Version that you want to download
 | 
			
		||||
    #[clap(short, long, env = "CLIN_VERSION")]
 | 
			
		||||
    #[clap(short, long, env = "DUDO_PACKAGE_VERSION")]
 | 
			
		||||
    package_version: String,
 | 
			
		||||
    /// Path to download
 | 
			
		||||
    #[clap(short, long, env = "CLIN_PATH")]
 | 
			
		||||
    install_path: String,
 | 
			
		||||
    #[clap(short, long, env = "DUDO_DOWNLOADPATH")]
 | 
			
		||||
    download_path: String,
 | 
			
		||||
    /// Path to dudo config file
 | 
			
		||||
    #[clap(short, long, default_value = "", env = "DUDO_CONFIG")]
 | 
			
		||||
    config: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Serialize, Deserialize)]
 | 
			
		||||
struct Values {
 | 
			
		||||
struct SystemValues {
 | 
			
		||||
    version: String,
 | 
			
		||||
    os: String,
 | 
			
		||||
    arch: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Serialize, Deserialize, Debug)]
 | 
			
		||||
struct Config {
 | 
			
		||||
    os: HashMap<String, Vec<String>>,
 | 
			
		||||
    arch: HashMap<String, Vec<String>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    // Initial steps
 | 
			
		||||
    env_logger::init();
 | 
			
		||||
    let args = Args::parse();
 | 
			
		||||
    let mut reg = Handlebars::new();
 | 
			
		||||
    reg.register_template_string("download_link", args.link_template)
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    let archs: Vec<String> = match ARCH {
 | 
			
		||||
        "x86_64" => vec!["x86_64".to_string(), "amd64".to_string()],
 | 
			
		||||
        "aarch64" => vec!["aarch64".to_string(), "arm64".to_string()],
 | 
			
		||||
        _ => {
 | 
			
		||||
            error!("Unknown architecture");
 | 
			
		||||
    // Register download url template
 | 
			
		||||
    let mut reg = Handlebars::new();
 | 
			
		||||
    match reg.register_template_string("download_link", args.link_template) {
 | 
			
		||||
        Ok(_) => info!("Your template is successfully registered"),
 | 
			
		||||
        Err(err) => error!("{}", err),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Set system aliases
 | 
			
		||||
    let config = match parse_config(args.config) {
 | 
			
		||||
        Ok(config) => config,
 | 
			
		||||
        Err(err) => {
 | 
			
		||||
            error!("{}", err);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for arch in archs {
 | 
			
		||||
        let version = args.package_version.clone();
 | 
			
		||||
        let os = OS.to_string();
 | 
			
		||||
        let values = Values { arch, os, version };
 | 
			
		||||
    info!("Running on {} {}", OS, ARCH);
 | 
			
		||||
    let oss = config.os.get(&OS.clone().to_string()).unwrap();
 | 
			
		||||
    let archs = config.arch.get(&ARCH.clone().to_string()).unwrap();
 | 
			
		||||
 | 
			
		||||
        let link = reg.render("download_link", &values).unwrap();
 | 
			
		||||
        info!("Trying to download from {}", link.clone());
 | 
			
		||||
        let mut resp = reqwest::blocking::get(link).unwrap();
 | 
			
		||||
        if resp.status() == StatusCode::OK {
 | 
			
		||||
            info!("Response is 200, I'll try to download");
 | 
			
		||||
            let mut out = File::create(args.install_path).expect("failed to create file");
 | 
			
		||||
            io::copy(&mut resp, &mut out).expect("failed to copy content");
 | 
			
		||||
            break;
 | 
			
		||||
    for arch in archs {
 | 
			
		||||
        for os in oss {
 | 
			
		||||
            let version = args.package_version.clone();
 | 
			
		||||
            let values = SystemValues {
 | 
			
		||||
                arch: arch.clone(),
 | 
			
		||||
                os: os.clone(),
 | 
			
		||||
                version,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            let link = reg.render("download_link", &values).unwrap();
 | 
			
		||||
            info!("Trying to download from {}", link.clone());
 | 
			
		||||
            let mut resp = reqwest::blocking::get(link).unwrap();
 | 
			
		||||
            if resp.status() == StatusCode::OK {
 | 
			
		||||
                info!("Response is 200, I'll try to download");
 | 
			
		||||
                let mut out =
 | 
			
		||||
                    File::create(args.download_path.clone()).expect("failed to create file");
 | 
			
		||||
                io::copy(&mut resp, &mut out).expect("failed to copy content");
 | 
			
		||||
                exit(0);
 | 
			
		||||
            }
 | 
			
		||||
            info!("Will try another name for arch, because response is not 200");
 | 
			
		||||
        }
 | 
			
		||||
        info!("Will try another name for arch, because response is not 200");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn parse_config(config_path: String) -> Result<Config> {
 | 
			
		||||
    let config_res: std::result::Result<Config, _>;
 | 
			
		||||
    if config_path.is_empty() {
 | 
			
		||||
        config_res = serde_yaml::from_str(CONFIG);
 | 
			
		||||
    } else {
 | 
			
		||||
        let f = OpenOptions::new().write(false).read(true).open(config_path);
 | 
			
		||||
        let f = match f {
 | 
			
		||||
            Ok(file) => file,
 | 
			
		||||
            Err(err) => {
 | 
			
		||||
                return Err(err.into());
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        config_res = serde_yaml::from_reader(f);
 | 
			
		||||
    }
 | 
			
		||||
    match config_res {
 | 
			
		||||
        Ok(config) => Ok(config),
 | 
			
		||||
        Err(err) => Err(err.into()),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use crate::parse_config;
 | 
			
		||||
    use std::io::Write;
 | 
			
		||||
    use tempfile::NamedTempFile;
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn parse_config_default() {
 | 
			
		||||
        let config = parse_config("".to_owned()).unwrap();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.os.get("linux").unwrap().clone(),
 | 
			
		||||
            vec!["linux".to_string()]
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.os.get("windows").unwrap().clone(),
 | 
			
		||||
            vec!["windows".to_string()]
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.os.get("macos").unwrap().clone(),
 | 
			
		||||
            vec![
 | 
			
		||||
                "macos".to_string(),
 | 
			
		||||
                "darwin".to_string(),
 | 
			
		||||
                "mac".to_string(),
 | 
			
		||||
                "apple".to_string(),
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.arch.get("x86_64").unwrap().clone(),
 | 
			
		||||
            vec![
 | 
			
		||||
                "x86_64".to_string(),
 | 
			
		||||
                "amd64".to_string(),
 | 
			
		||||
                "amd".to_string(),
 | 
			
		||||
                "intel".to_string(),
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.arch.get("aarch64").unwrap().clone(),
 | 
			
		||||
            vec!["aarch64".to_string(), "arm64".to_string(), "m1".to_string(),]
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn parse_config_custom() {
 | 
			
		||||
        let config = "
 | 
			
		||||
---
 | 
			
		||||
os:
 | 
			
		||||
  macos:
 | 
			
		||||
    - macos
 | 
			
		||||
  linux:
 | 
			
		||||
    - linux
 | 
			
		||||
  windows:
 | 
			
		||||
    - windows
 | 
			
		||||
  freebsd:
 | 
			
		||||
    - freebsd
 | 
			
		||||
arch:
 | 
			
		||||
  x86_64:
 | 
			
		||||
    - x86_64
 | 
			
		||||
  aarch64:
 | 
			
		||||
    - aarch64
 | 
			
		||||
        ";
 | 
			
		||||
        let mut file = NamedTempFile::new().unwrap();
 | 
			
		||||
        writeln!(file, "{}", config).unwrap();
 | 
			
		||||
        let path = file.into_temp_path();
 | 
			
		||||
        // It's looking damn not right
 | 
			
		||||
        let config = parse_config(path.to_str().unwrap().clone().to_string()).unwrap();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.os.get("linux").unwrap().clone(),
 | 
			
		||||
            vec!["linux".to_string()]
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.os.get("windows").unwrap().clone(),
 | 
			
		||||
            vec!["windows".to_string()]
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.os.get("macos").unwrap().clone(),
 | 
			
		||||
            vec!["macos".to_string()]
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.arch.get("x86_64").unwrap().clone(),
 | 
			
		||||
            vec!["x86_64".to_string()]
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            config.arch.get("aarch64").unwrap().clone(),
 | 
			
		||||
            vec!["aarch64".to_string()]
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user