Giter VIP home page Giter VIP logo

cargo's Introduction

Hey Friends

linked-in badge Web badge

My name is Jordan, but some call me JT. I'm a senior platform engineer juggling a few side projects with Go, .NET.

  • ๐Ÿ—๏ธ Iโ€™m diving into Software Engineering and Distributed Systems in the Go ecosystem.
  • ๐Ÿ’ฌ Ask me about CI/CD infrastructure.
  • โšก What I am learning currently - AWS - SNS, SQS, DynamoDB, Event-Driven architecture.

Recent posts I published on my blog

last update: Fri, 12 Apr 2024

cargo's People

Contributors

justjordant avatar

Stargazers

 avatar

Watchers

 avatar

cargo's Issues

Build an installer service

Create a service function that can install the compiled package on the user's system. You can use Go's built-in os/exec package to run shell commands to install the package.

To add support for macOS in addition to Linux and Windows, you would need to modify the installPackage function to include a platform-specific command for macOS. Here's an updated implementation that supports all three operating systems:

package main

import (
    "fmt"
    "os"
    "os/exec"
    "runtime"
)

func installPackage(packagePath string) error {
    // Check if the package path exists
    if _, err := os.Stat(packagePath); os.IsNotExist(err) {
        return fmt.Errorf("Package %s does not exist", packagePath)
    }

    // Determine the platform-specific installation command
    var cmd *exec.Cmd
    switch runtime.GOOS {
    case "linux":
        if _, err := exec.LookPath("dpkg"); err == nil {
            // Debian-based
            cmd = exec.Command("sudo", "dpkg", "-i", packagePath)
        } else if _, err := exec.LookPath("rpm"); err == nil {
            // RPM-based
            cmd = exec.Command("sudo", "rpm", "-i", packagePath)
        } else {
            return fmt.Errorf("Unsupported package manager")
        }
    case "windows":
        cmd = exec.Command("cmd", "/c", "msiexec", "/i", packagePath, "/qn")
    case "darwin":
        cmd = exec.Command("sudo", "installer", "-pkg", packagePath, "-target", "/")
    default:
        return fmt.Errorf("Unsupported operating system: %s", runtime.GOOS)
    }

    // Run the installation command
    if err := cmd.Run(); err != nil {
        return fmt.Errorf("Error installing package: %v", err)
    }

    return nil
}

In this implementation, we add a new case for the linux platform and check for the presence of both dpkg and rpm commands. If dpkg is available, we use the Debian-based installation command like before. If rpm is available, we use the RPM-based installation command with the -i flag to install the package. If neither command is available, we return an error indicating that the package manager is unsupported.

With these changes, the installPackage function can now install packages on Debian-based and RPM-based Linux distributions, as well as macOS and Windows systems. Note that this implementation is just an example and may need to be modified depending on the specific requirements of your package manager.

Gotchas

  • Should we care if this is a private repo and if so should we pass this in logically so that we are handling this from the Go side of the house.

Build a Parser - Being able to parse Cargo for crates

To create a Go application that parses a GitHub repository with a folder named "crates" located at https://github.com/justjordant/cargo-crates/tree/master/crates, you can use the following code:

package main

import (
	"context"
	"fmt"
	"github.com/google/go-github/v37/github"
	"golang.org/x/oauth2"
)

func main() {
	ctx := context.Background()

	// Set up a new GitHub client with an access token
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: "YOUR_ACCESS_TOKEN_HERE"},
	)
	tc := oauth2.NewClient(ctx, ts)
	client := github.NewClient(tc)

	// Get the contents of the "crates" folder
	_, dirContents, _, err := client.Repositories.GetContents(ctx, "justjordant", "porter-crates", "crates", &github.RepositoryContentGetOptions{})
	if err != nil {
		panic(err)
	}

	// Iterate through the contents of the "crates" folder
	for _, content := range dirContents {
		if content.GetType() == "dir" {
			// If the content is a directory, get its contents as well
			_, subDirContents, _, err := client.Repositories.GetContents(ctx, "justjordant", "porter-crates", content.GetPath(), &github.RepositoryContentGetOptions{})
			if err != nil {
				panic(err)
			}

			// Print the names of the files in the subdirectory
			for _, subContent := range subDirContents {
				fmt.Println(subContent.GetName())
			}
		} else {
			// If the content is a file, print its name
			fmt.Println(content.GetName())
		}
	}
}

This code uses the go-github package to authenticate with the GitHub API and retrieve the contents of the "crates" folder at https://github.com/justjordant/cargo-crates/tree/master/crates. It then iterates through the contents of the "crates" folder and prints the names of any files or subdirectories it finds.

Make sure to replace "YOUR_ACCESS_TOKEN_HERE" with a valid access token that has access to the "justjordant/porter-crates" repository.

Thoughts

  • Should a user be able to use Tokens for auth to GH or should this only be done on oAuth
  • This would be more secure, but limit the use case for being able to manage this on a server.

Gotchas

Build a downloader service

Build a downloader: Create a function to download a package from its URL and save it to disk. You can use Go's built-in net/http package to download files.

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func downloadFile(url string, filepath string) error {
    // Create the file
    out, err := os.Create(filepath)
    if err != nil {
        return err
    }
    defer out.Close()

    // Get the data
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    // Check server response
    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("bad status: %s", resp.Status)
    }

    // Writer the body to file
    _, err = io.Copy(out, resp.Body)
    if err != nil {
        return err
    }

    return nil
}

func deleteFile(filepath string) error {
    err := os.Remove(filepath)
    if err != nil {
        return err
    }
    return nil
}

func main() {
    url := "https://example.com/package.tar.gz"
    filepath := "/path/to/package.tar.gz"

    err := downloadFile(url, filepath)
    if err != nil {
        fmt.Println("Error downloading file:", err)
        return
    }

    fmt.Println("File downloaded successfully!")

    defer func() {
        // defer the file deletion until after main function is completed
        err := deleteFile(filepath)
        if err != nil {
            fmt.Println("Error deleting file:", err)
        }
    }()
}

Here, we have added a deleteFile function that uses the os.Remove function to delete the specified file. We then use a defer statement to schedule the deletion of the file after the main function has been completed. This way, the file will be automatically deleted even if the program encounters an error and exits early.

Note that defer statements are executed in a last-in-first-out (LIFO) order, so any defer statements that are added after the deleteFile statement will be executed before the file deletion.

Gotchas

  • The delete defer should only happen after an install this should be a func call that we can pass in at the time of install

Create a internal key-vault service

Key Vault Service.

This will be a service for storing and retrieving sensitive data based on the information that is passed into the conf YAML file that we will store. this means that we will need to have some sort of hash that is stored in the YAML that will then in turn be the look-up key for getting the API keys.

Work around to code signing MacOS

The OS refuses to run any downloaded binary that is not signed by an Apple developer account. A seasoned developer knows that they can use curl --output <file> -L <url-to-tar-gz-file> in order to circumvent that check; however, the standard Mac user wants a more convenient way.

https://appliedgo.net/release/

Logging Service

Create a Logging Service in Go with Zap Logging out to File

Logging is an essential aspect of software development that helps developers identify errors and diagnose problems in their code. In this tutorial, we will learn how to create a logging service in Go using the Zap logging library and output logs to a file.

Step 1: Installing Zap Logging Library

The first step is to install the Zap logging library. We can use the following command to install it:

go get -u go.uber.org/zap

Step 2: Creating a Logger

The next step is to create a logger. We can use the following code to create a logger that outputs logs to a file:

package main

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

func main() {
	// create a zap config
	cfg := zap.Config{
		Encoding: "json",
		Level:    zap.NewAtomicLevelAt(zap.DebugLevel),
		OutputPaths: []string{
			"./logs.log",
		},
		ErrorOutputPaths: []string{
			"./errors.log",
		},
		EncoderConfig: zapcore.EncoderConfig{
			MessageKey: "message",
			LevelKey:   "level",
			TimeKey:    "time",
			CallerKey:  "caller",
			EncodeTime: zapcore.ISO8601TimeEncoder,
		},
	}

	// create a zap logger
	logger, err := cfg.Build()
	if err != nil {
		panic(err)
	}

	// use the logger
	logger.Info("Hello, world!")
}

In the above code, we create a Zap configuration that specifies the output to a file. We set the encoding to JSON, the log level to debug, and the output and error paths to './logs.log' and './errors.log', respectively. We also specify the encoder configuration with the relevant keys and set the time encoder to ISO8601.

Once we have the configuration, we can create a Zap logger using the Build method. If there is an error, we panic and terminate the program. Finally, we use the logger to output an info log with the message "Hello, world!".

Step 3: Using the Logger

Now that we have created a logger, we can use it to output logs throughout our program. We can use the following code to output a log:

logger.Info("This is an info log.")
logger.Warn("This is a warning log.")
logger.Error("This is an error log.")

In the above code, we use the logger to output an info log, a warning log, and an error log.

Resources

uber-go/zap#426
https://gosamples.dev/create-file/
https://stackoverflow.com/questions/57745017/how-to-initialize-a-zap-logger-once-and-reuse-it-in-other-go-files
https://github.com/uber-go/zap
https://www.youtube.com/watch?v=PfXiyqg4JuY
https://www.youtube.com/watch?v=Lbiz-PZNiU0

BASH Installer

Starting point...

#!/usr/bin/env bash

dirname="foo"

# Create the directory under /usr/local with group ownership set to "admin"
sudo mkdir "/usr/local/$dirname"
sudo chown :admin "/usr/local/$dirname"

# Change the owner of the directory to local user
sudo chown $USER "/usr/local/$dirname"

# Check if the directory was created, group ownership was set, and owner was changed successfully
if [ $? -eq 0 ]; then
  echo "Directory '$dirname' created successfully under /usr/local with group ownership set to 'admin' and owner changed to '$USER'"
else
  echo "Failed to create directory '$dirname', set group ownership to 'admin', or change owner to '$USER'"
fi

In this version of the script, we've used sudo to create the directory "foo" under /usr/local, and then used sudo chown to set the group ownership of the directory to "admin". The rest of the script remains the same, and it will provide feedback on whether the directory was created and group ownership was set successfully or not. Please use caution when using sudo and make sure to understand the implications of running commands with administrative privileges. Additionally, ensure that the "admin" group exists on your system before using it as the group ownership.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.