Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
simaotwx committed Jun 30, 2021
0 parents commit da43243
Show file tree
Hide file tree
Showing 8 changed files with 985 additions and 0 deletions.
94 changes: 94 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

# Log files
logs/

*.DS_Store
*thumbs.db

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
NAME:=docker
BINARY=terraform-provider-${NAME}
VERSION=0.0.1
OS_ARCH=linux_amd64

default: build

build:
go build -o ${BINARY}

release:
GOOS=darwin GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_darwin_amd64
GOOS=freebsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_freebsd_amd64
GOOS=freebsd GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_freebsd_arm
GOOS=linux GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_linux_amd64
GOOS=linux GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_linux_arm
GOOS=openbsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_openbsd_amd64
GOOS=solaris GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_solaris_amd64
GOOS=windows GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_windows_amd64

142 changes: 142 additions & 0 deletions docker/data_sources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package docker

import (
"context"
"fmt"
"log"
"strings"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/heroku/docker-registry-client/registry"
"github.com/pkg/errors"
"gitlab.com/xdevs23/go-collections"
)

func dataSourceDockerImageWait() *schema.Resource {
return &schema.Resource{
Description: "Waits for a docker image to be available",
ReadContext: dataSourceDockerImageWaitRead,
Schema: map[string]*schema.Schema{
"registry": {
Description: "Registry URL",
Type: schema.TypeString,
Default: "registry.hub.docker.com",
Optional: true,
ForceNew: true,
},
"username": {
Description: "Username to log in",
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Sensitive: true,
},
"password": {
Description: "Password to log in",
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Sensitive: true,
},
"image": {
Description: "Docker image",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"timeout": {
Description: "How long to wait, in seconds",
Type: schema.TypeInt,
Optional: true,
Default: 600,
ForceNew: true,
},
"id": {
Description: "Returns an ID that changes every time",
Computed: true,
Type: schema.TypeString,
},
"exists": {
Description: "Returns true if the image exists after waiting for it",
Computed: true,
Type: schema.TypeBool,
},
},
}
}

func dataSourceDockerImageWaitRead(
ctx context.Context,
d *schema.ResourceData,
m interface{},
) diag.Diagnostics {
url := "https://" + d.Get("registry").(string)
username := ""
password := ""
if strI, ok := d.GetOk("username"); ok {
username = strI.(string)
}
if strI, ok := d.GetOk("password"); ok {
password = strI.(string)
}
image := d.Get("image").(string)

var repository string
tag := "latest"
splitImage := strings.Split(image, ":")
if len(splitImage) == 0 {
return diag.Errorf("invalid image \"%s\", please specify an image", image)
}
if len(splitImage) >= 1 {
repository = splitImage[0]
}
if len(splitImage) == 2 {
tag = splitImage[1]
}
if len(splitImage) > 2 {
return diag.Errorf("invalid image \"%s\": found more than one colon", image)
}

if err := waitForImage(url, username, password, repository, tag, d.Get("timeout").(int)); err != nil {
return diag.FromErr(err)
}

d.SetId(fmt.Sprintf("%d", time.Now().Unix()))
if err := d.Set("exists", true); err != nil {
return diag.FromErr(errors.Wrap(err, "bug: could not set 'exists' output"))
}

return nil
}

func waitForImage(url string, username string, password string, repository string, tag string, timeout int) error {
hub, err := registry.New(url, username, password)
if err != nil {
return errors.Wrap(err, "could not connect/log in to registry")
}

ranIntoTimeout := false

time.AfterFunc(time.Duration(timeout)*time.Second, func() {
ranIntoTimeout = true
})

for {
tags, err := hub.Tags(repository)
if err != nil || !collections.Include(tags, tag) {
if err != nil {
log.Println(err)
}
if ranIntoTimeout {
break
}
time.Sleep(500 * time.Millisecond)
continue
}
break
}

return nil
}
13 changes: 13 additions & 0 deletions docker/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package docker

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// Provider -
func Provider() *schema.Provider {
return &schema.Provider{
ResourcesMap: map[string]*schema.Resource{},
DataSourcesMap: map[string]*schema.Resource{},
}
}
14 changes: 14 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module terraform-provider-docker

go 1.16

require (
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0
github.com/heroku/docker-registry-client v0.0.0-20190909225348-afc9e1acc3d5
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/pkg/errors v0.9.1
gitlab.com/xdevs23/go-collections v0.1.0 // indirect
)
Loading

0 comments on commit da43243

Please sign in to comment.