### Install the YAML package Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/go.yaml.in/yaml/v3/README.md Use the go get command to add the package to your Go project. ```bash go get go.yaml.in/yaml/v3 ``` -------------------------------- ### Convert format string logs to structured key-value pairs Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/go-logr/logr/README.md Examples demonstrating the migration from klog format strings to structured logr-style key-value logging. ```go klog.V(4).Infof("Client is returning errors: code %v, error %v", responseCode, err) ``` ```go logger.Error(err, "client returned an error", "code", responseCode) ``` ```go klog.V(4).Infof("Got a Retry-After %ds response for attempt %d to %v", seconds, retries, url) ``` ```go logger.V(4).Info("got a retry-after response when requesting url", "attempt", retries, "after seconds", seconds, "url", url) ``` -------------------------------- ### Install Counterfeiter to `$GOPATH/bin` Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md This command installs `counterfeiter` globally to your `$GOPATH/bin` directory, allowing you to invoke it from your shell outside of a Go module context. This method is generally unnecessary if using `go generate`. ```shell go install github.com/maxbrunsfeld/counterfeiter/v6 ~/go/bin/counterfeiter USAGE counterfeiter [-generate>] [-o ] [-p] [--fake-name ] [-header ] [] [-] ``` -------------------------------- ### Install BBR with Homebrew Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/README.md Use this command to install BBR on macOS using Homebrew. Ensure you have tapped the cloudfoundry/tap repository first. ```bash brew tap cloudfoundry/tap brew install bbr ``` -------------------------------- ### Define a Ginkgo test suite Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/onsi/ginkgo/v2/README.md Uses Describe, Context, and When blocks to structure test scenarios, with BeforeEach for setup and It for individual test cases. ```go import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ... ) var _ = Describe("Checking books out of the library", Label("library"), func() { var library *libraries.Library var book *books.Book var valjean *users.User BeforeEach(func() { library = libraries.NewClient() book = &books.Book{ Title: "Les Miserables", Author: "Victor Hugo", } valjean = users.NewUser("Jean Valjean") }) When("the library has the book in question", func() { BeforeEach(func(ctx SpecContext) { Expect(library.Store(ctx, book)).To(Succeed()) }) Context("and the book is available", func() { It("lends it to the reader", func(ctx SpecContext) { Expect(valjean.Checkout(ctx, library, "Les Miserables")).To(Succeed()) Expect(valjean.Books()).To(ContainElement(book)) Expect(library.UserWithBook(ctx, book)).To(Equal(valjean)) }, SpecTimeout(time.Second * 5)) }) Context("but the book has already been checked out", func() { var javert *users.User BeforeEach(func(ctx SpecContext) { javert = users.NewUser("Javert") Expect(javert.Checkout(ctx, library, "Les Miserables")).To(Succeed()) }) It("tells the user", func(ctx SpecContext) { err := valjean.Checkout(ctx, library, "Les Miserables") Expect(err).To(MatchError("Les Miserables is currently checked out")) }, SpecTimeout(time.Second * 5)) It("lets the user place a hold and get notified later", func(ctx SpecContext) { Expect(valjean.Hold(ctx, library, "Les Miserables")).To(Succeed()) Expect(valjean.Holds(ctx)).To(ContainElement(book)) By("when Javert returns the book") Expect(javert.Return(ctx, library, book)).To(Succeed()) By("it eventually informs Valjean") notification := "Les Miserables is ready for pick up" Eventually(ctx, valjean.Notifications).Should(ContainElement(notification)) Expect(valjean.Checkout(ctx, library, "Les Miserables")).To(Succeed()) Expect(valjean.Books(ctx)).To(ContainElement(book)) Expect(valjean.Holds(ctx)).To(BeEmpty()) }, SpecTimeout(time.Second * 10)) }) }) When("the library does not have the book in question", func() { It("tells the reader the book is unavailable", func(ctx SpecContext) { err := valjean.Checkout(ctx, library, "Les Miserables") Expect(err).To(MatchError("Les Miserables is not in the library catalog")) }, SpecTimeout(time.Second * 5)) }) }) ``` -------------------------------- ### Download Go Modules for BBR Development Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/README.md Clone the BBR repository and download its Go module dependencies to set up a local development environment. Ensure Git and Go are installed. ```bash git clone git@github.com:cloudfoundry-incubator/bosh-backup-and-restore. go mod download ``` -------------------------------- ### Generate Function with Positional Args Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/aws/smithy-go/AGENTS.md Example of using `writer.openBlock` and `writer.write` with positional arguments to generate a Go function signature and body. Arguments like `$P` (Pointable type) and `$T` (Type) automatically handle imports and type formatting. ```java writer.openBlock("func (c $P) $T(ctx $T) ($P, error) {", "}", serviceSymbol, operationSymbol, contextSymbol, outputSymbol, () -> { writer.write("return nil, nil"); }); ``` -------------------------------- ### Generate Struct with Positional Args Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/aws/smithy-go/AGENTS.md Example of using `writer.write` with positional arguments to generate a Go struct definition. Note the use of `$1L` and `$2L` for literal arguments. ```java // $1L is used twice, $2L once — only 2 args needed writer.write("type $1L struct{}\nvar _ $2L = (*$1L)(nil)", DEFAULT_NAME, INTERFACE_NAME); ``` -------------------------------- ### BBR S3 Bucket Configuration File Structure Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/README.md Example JSON structure for configuring S3-compatible blobstore access for BBR. It includes credentials, endpoint, bucket names, and regions for both live and backup buckets. ```json { "some-resource-to-backup": { "aws_access_key_id": "", "aws_secret_access_key": "", "endpoint": "", "name": "", "region": "", "backup": { "name": "", "region": "" } }, "another-resource-to-backup": { ... }, ... } ``` -------------------------------- ### Initialize the root logger Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/go-logr/logr/README.md Create a root logger instance using a specific logging implementation early in the application lifecycle. ```go func main() { // ... other setup code ... // Create the "root" logger. We have chosen the "logimpl" implementation, // which takes some initial parameters and returns a logr.Logger. logger := logimpl.New(param1, param2) // ... other setup code ... ``` -------------------------------- ### YAML processing output Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/go.yaml.in/yaml/v3/README.md The expected output generated by the marshaling and unmarshaling example. ```text --- t: {Easy! {2 [3 4]}} --- t dump: a: Easy! b: c: 2 d: [3, 4] --- m: map[a:Easy! b:map[c:2 d:[3 4]]] --- m dump: a: Easy! b: c: 2 d: - 3 - 4 ``` -------------------------------- ### Run Gomega linter Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/onsi/gomega/CONTRIBUTING.md Check the codebase for potential issues using the Go vet tool. ```bash go vet ./... ``` -------------------------------- ### Instantiate a Fake Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md Import the generated fakes package and instantiate the fake by taking its address. This fake can then be used in tests. ```go import "my-repo/path/to/foo/foofakes" var fake = &foofakes.FakeMySpecialInterface{} ``` -------------------------------- ### SSH into Backup and Restore VM Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/README.md Connects to the backup and restore VM via SSH. Replace `` with your actual deployment name. ```shell bosh --deployment ssh backup_restore ``` -------------------------------- ### Run Gomega tests Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/onsi/gomega/CONTRIBUTING.md Execute all unit tests locally using Ginkgo. ```bash ginkgo -r -p ``` -------------------------------- ### Run Unit Tests (Go Runtime) Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/aws/smithy-go/AGENTS.md Execute unit tests for the Go runtime components of smithy-go. This command is used to ensure the integrity of the runtime packages. ```bash make unit ``` -------------------------------- ### Copy Validator Binary to VM Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/README.md Copies the validator binary to the backup and restore VM. Replace `` with your actual deployment name. ```shell bosh --deployment scp bbr-s3-config-validator-linux-amd64 backup_restore:/tmp ``` -------------------------------- ### List BOSH Deployments Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/README.md Use this command to find the deployment name before copying the validator binary. ```shell bosh deployments ``` -------------------------------- ### Generate Test Double for Local Interface Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md Use `go tool counterfeiter` with the package path and interface name to generate a fake. The fake will be written to a `fakes` subdirectory within the package. ```shell $ go tool counterfeiter path/to/foo MySpecialInterface ``` -------------------------------- ### Run `go generate` Command Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md Execute this command in your Go module's root directory or the specific package directory to generate the fake implementations. This command processes all `go:generate` directives. ```shell go generate ./... ``` -------------------------------- ### Check Version Against Constraints Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/Masterminds/semver/v3/README.md Use NewConstraint and NewVersion to validate if a specific version satisfies a defined range. ```go c, err := semver.NewConstraint(">= 1.2.3") if err != nil { // Handle constraint not being parsable. } v, err := semver.NewVersion("1.3") if err != nil { // Handle version not being parsable. } // Check if the version meets the constraints. The variable a will be true. a := c.Check(v) ``` -------------------------------- ### Configure Go Client Code Generation Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/aws/smithy-go/README.md This JSON configuration applies the `go-codegen` build plugin for Smithy models. It specifies the service, module, and Go directive. Ensure `smithy-build.json` is correctly configured for your project. ```json { "version": "1.0", "sources": [ "models" ], "maven": { "dependencies": [ "software.amazon.smithy.go:smithy-go-codegen:0.1.0" ] }, "plugins": { "go-codegen": { "service": "example.weather#Weather", "module": "github.com/example/weather", "generateGoMod": true, "goDirective": "1.24" } } } ``` -------------------------------- ### Commit, Push, and Create GitHub Release Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/onsi/ginkgo/v2/RELEASING.md Standard Git commands to commit changes, push to the remote repository, and create a new release on GitHub. Ensure the version number is correctly formatted. ```bash git commit -m "vM.m.p" git push gh release create "vM.m.p" git fetch --tags origin master ``` -------------------------------- ### Generate Test Double for Third-Party Interface Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md To generate a test double for a third-party interface, use the alternative syntax `.` with the `go tool counterfeiter` command. ```shell $ go tool counterfeiter github.com/go-redis/redis.Pipeliner ``` -------------------------------- ### Move Validator Binary to Home Directory Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/README.md Moves the validator binary from `/tmp` to your home directory on the VM, making it executable. ```shell mv /tmp/bbr-s3-config-validator-linux-amd64 . ``` -------------------------------- ### Generate Fakes with `counterfeiter:generate` Directives Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md For packages with multiple interfaces, use the `counterfeiter:generate` directive. This approach can significantly speed up the generation process. Ensure only one `go:generate` directive is present per package. ```go // You only need **one** of these per package! //go:generate go tool counterfeiter -generate // You will add lots of directives like these in the same package... //counterfeiter:generate . MySpecialInterface type MySpecialInterface interface { DoThings(string, uint64) (int, error) } // Like this... //counterfeiter:generate . MyOtherInterface type MyOtherInterface interface { DoOtherThings(string, uint64) (int, error) } ``` -------------------------------- ### System call entry points Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/golang.org/x/sys/unix/README.md Assembly entry points for system call dispatch, implemented for each GOOS/GOARCH pair. ```go func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) ``` -------------------------------- ### Generate Fake with `go:generate` Directive Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md Add this `go:generate` directive to a Go file containing your interface. Running `go generate ./...` will then create a fake implementation for the specified interface. ```go //go:generate go tool counterfeiter . MySpecialInterface type MySpecialInterface interface { DoThings(string, uint64) (int, error) } ``` -------------------------------- ### Add Counterfeiter as a Tool Dependency Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md Use this command to add `counterfeiter` as a tool dependency in your Go module. This is a prerequisite for using `go generate` with `counterfeiter`. ```shell go get -tool github.com/maxbrunsfeld/counterfeiter/v6 ``` -------------------------------- ### Load Slim-Sprig FuncMap Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/go-task/slim-sprig/v3/README.md The FuncMap must be registered with the template object before parsing any template files. ```go import ( "html/template" "github.com/go-task/slim-sprig" ) // This example illustrates that the FuncMap *must* be set before the // templates themselves are loaded. tpl := template.Must( template.New("base").Funcs(sprig.FuncMap()).ParseGlob("*.html") ) ``` -------------------------------- ### Display Validator Help Information Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/README.md Shows detailed usage instructions and available flags for the BBR S3 config validator. ```shell ./bbr-s3-config-validator-linux-amd64 --help ``` -------------------------------- ### Run Ginkgo Specs in Parallel Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/onsi/ginkgo/v2/README.md Use the '-p' flag with the ginkgo CLI to run your test suite in parallel. This is useful for speeding up execution of large integration suites. ```bash ginkgo -p ``` -------------------------------- ### Generate Go Function with Named Template Args Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/aws/smithy-go/AGENTS.md Use `goTemplate` with named arguments to define a Go function. Arguments are passed as a map, and this method returns a `Writable` that does not write immediately. This is the preferred style for new code due to its readability and reduced error potential. ```java return goTemplate("\n func $name:L(v $cborValue:T) ($type:T, error) {\n return $coercer:T(v)\n }\n ", Map.of( "name", getDeserializerName(shape), "cborValue", SmithyGoTypes.Encoding.Cbor.Value, "type", symbolProvider.toSymbol(shape), "coercer", coercer )); ``` -------------------------------- ### Build and Test Codegen (Java) Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/aws/smithy-go/AGENTS.md Build and test the Java-based Smithy code generator. This command is essential for verifying the codegen module before publishing. ```bash cd codegen && ./gradlew build ``` -------------------------------- ### Run BBR S3 Config Validator Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/README.md Executes the validator tool with default settings, validating the configuration at `/var/vcap/jobs/s3-versioned-blobstore-backup-restorer/config/buckets.json`. ```shell ./bbr-s3-config-validator-linux-amd64 ``` -------------------------------- ### Marshal and Unmarshal YAML data Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/go.yaml.in/yaml/v3/README.md Demonstrates how to decode YAML into a struct or map, and encode them back into YAML format. Struct fields must be exported to be accessible by the unmarshaler. ```go package main import ( "fmt" "log" "go.yaml.in/yaml/v3" ) var data = ` a: Easy! b: c: 2 d: [3, 4] ` // Note: struct fields must be public in order for unmarshal to // correctly populate the data. type T struct { A string B struct { RenamedC int `yaml:"c"` D []int `yaml:",flow"` } } func main() { t := T{} err := yaml.Unmarshal([]byte(data), &t) if err != nil { log.Fatalf("error: %v", err) } fmt.Printf("--- t:\n%v\n\n", t) d, err := yaml.Marshal(&t) if err != nil { log.Fatalf("error: %v", err) } fmt.Printf("--- t dump:\n%s\n\n", string(d)) m := make(map[interface{}]interface{}) err = yaml.Unmarshal([]byte(data), &m) if err != nil { log.Fatalf("error: %v", err) } fmt.Printf("--- m:\n%v\n\n", m) d, err = yaml.Marshal(&m) if err != nil { log.Fatalf("error: %v", err) } fmt.Printf("--- m dump:\n%s\n\n", string(d)) } ``` -------------------------------- ### Handle format strings in key values Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/go-logr/logr/README.md Use fmt.Sprintf when a format string is strictly necessary within a structured log value. ```go log.Printf("unable to reflect over type %T") ``` ```go logger.Info("unable to reflect over type", "type", fmt.Sprintf("%T")) ``` -------------------------------- ### Changelog Entry Format Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/aws/smithy-go/CONTRIBUTING.md Use this JSON format for changelog files. The 'id' should match the filename. 'type' indicates the nature of the change, and 'collapse' determines its display in release notes. ```json { "id": "12345678-1234-1234-1234-123456789012" "type": "bugfix" "collapse": true "description": "Fix improper use of printf-style functions.", "modules": [ "." ] } ``` -------------------------------- ### Run BBR Unit Tests Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/README.md Execute all unit tests for BBR. This command requires Docker to be running for networking tests. ```bash make test ``` -------------------------------- ### Validate Version Against Constraint in Go Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/Masterminds/semver/v3/README.md Use the Validate method to check if a version meets a specific constraint and retrieve error messages if it fails. ```go c, err := semver.NewConstraint("<= 1.2.3, >= 1.4") if err != nil { // Handle constraint not being parseable. } v, err := semver.NewVersion("1.3") if err != nil { // Handle version not being parseable. } // Validate a version against a constraint. a, msgs := c.Validate(v) // a is false for _, m := range msgs { fmt.Println(m) // Loops over the errors which would read // "1.3 is greater than 1.2.3" // "1.3 is less than 1.4" } ``` -------------------------------- ### Counterfeiter CLI Usage within a Go Module Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md Invoke `counterfeiter` directly using `go tool` within your Go module. This command displays the usage instructions for the `counterfeiter` tool. ```shell go tool counterfeiter USAGE counterfeiter [-generate>] [-o ] [-p] [--fake-name ] [-header ] [] [-] ``` -------------------------------- ### Record Arguments and Call Count Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/maxbrunsfeld/counterfeiter/v6/README.md Fakes record the arguments they are called with and the number of times they are called. Use `CallCount` to check how many times a method was invoked and `ArgsForCall` to retrieve the arguments from a specific call. ```go fake.DoThings("stuff", 5) Expect(fake.DoThingsCallCount()).To(Equal(1)) str, num := fake.DoThingsArgsForCall(0) Expect(str).To(Equal("stuff")) Expect(num).To(Equal(uint64(5))) ``` -------------------------------- ### Run BBR Unit Tests with Reduced Nodes Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/README.md If experiencing timeout errors in SSH tests, reduce the number of nodes to decrease concurrent requests to the Docker daemon. Adjust `` as needed. ```bash ginkgo -nodes= -r ``` -------------------------------- ### Pass the logger to application components Source: https://github.com/cloudfoundry/bosh-backup-and-restore/blob/master/s3-config-validator/src/vendor/github.com/go-logr/logr/README.md Inject the logger instance into application objects to enable logging across different components. ```go app := createTheAppObject(logger) app.Run() ```