Initial commit
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
commit
7f2e6734ce
|
@ -0,0 +1,15 @@
|
||||||
|
kind: pipeline
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
registry: registry.makerforce.io
|
||||||
|
repo: registry.makerforce.io/cacti/he-dns-editor
|
||||||
|
tags:
|
||||||
|
- latest
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
|
@ -0,0 +1 @@
|
||||||
|
he-dns-editor
|
|
@ -0,0 +1,36 @@
|
||||||
|
FROM golang:1.11-alpine as build
|
||||||
|
|
||||||
|
# args
|
||||||
|
ARG version="0.1"
|
||||||
|
ARG repo="git.makerforce.io/cacti/he-dns-editor"
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
RUN apk add --no-cache ca-certificates
|
||||||
|
|
||||||
|
# source
|
||||||
|
WORKDIR $GOPATH/src/${repo}
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# build
|
||||||
|
ENV CGO_ENABLED=0
|
||||||
|
ENV GOOS=linux
|
||||||
|
ENV GOARCH=amd64
|
||||||
|
RUN go build -ldflags "-s -w" -o /he-dns-editor
|
||||||
|
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
ARG version
|
||||||
|
|
||||||
|
# labels
|
||||||
|
LABEL org.label-schema.vcs-url="https://git.makerforce.io/cacti/he-dns-editor"
|
||||||
|
LABEL org.label-schema.version=${version}
|
||||||
|
LABEL org.label-schema.schema-version="1.0"
|
||||||
|
|
||||||
|
# copy binary and ca certs
|
||||||
|
COPY --from=build /he-dns-editor /email-collector
|
||||||
|
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
ENTRYPOINT ["/he-dns-editor"]
|
|
@ -0,0 +1,6 @@
|
||||||
|
module git.makerforce.io/cacti/he-dns-editor
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
@ -0,0 +1,203 @@
|
||||||
|
package main // import "git.makerforce.io/cacti/he-dns-editor"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
var listen string
|
||||||
|
var username string
|
||||||
|
var password string
|
||||||
|
var zoneid string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.StringVar(&listen, "listen", ":8080", "Listen on port")
|
||||||
|
flag.StringVar(&username, "username", "", "HE.net username")
|
||||||
|
flag.StringVar(&password, "password", "", "HE.net password")
|
||||||
|
flag.StringVar(&zoneid, "zoneid", "", "HE.net zone ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
if len(username) == 0 || len(password) == 0 || len(zoneid) == 0 {
|
||||||
|
flag.PrintDefaults()
|
||||||
|
log.Fatal("Please specify username, password and zoneid")
|
||||||
|
}
|
||||||
|
|
||||||
|
router := httprouter.New()
|
||||||
|
router.GET("/", Index)
|
||||||
|
router.POST("/", Post)
|
||||||
|
|
||||||
|
// Listen
|
||||||
|
log.Println("main: Listening on", listen)
|
||||||
|
log.Fatal(http.ListenAndServe(listen, router))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
w.Header().Add("Content-Type", "text/html")
|
||||||
|
records, err := request("", "", "", "", "")
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
w.Write([]byte("An error occurred"))
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res := `
|
||||||
|
<style>
|
||||||
|
form {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<main>`
|
||||||
|
for _, record := range records {
|
||||||
|
disabled := ""
|
||||||
|
if record.Type == "NS" || record.Type == "SOA" {
|
||||||
|
disabled = ` disabled`
|
||||||
|
}
|
||||||
|
res += `<form method="POST">`
|
||||||
|
res += `<input type="hidden" name="recordid" value="` + record.ID + `"` + disabled + `>`
|
||||||
|
res += `<input name="recordname" value="` + record.Name + `"` + disabled + `>`
|
||||||
|
res += `<input name="recordtype" value="` + record.Type + `"` + disabled + `>`
|
||||||
|
res += `<input name="recordcontent" value="` + record.Content + `"` + disabled + `>`
|
||||||
|
res += `<input type="submit" name="editrecord" value="Update"` + disabled + `>`
|
||||||
|
res += `<input type="submit" name="editrecord" value="Delete"` + disabled + `>`
|
||||||
|
res += `</form>`
|
||||||
|
}
|
||||||
|
res += `<form method="POST">`
|
||||||
|
res += `<input name="recordname" placeholder="Name">`
|
||||||
|
res += `<input name="recordtype" placeholder="Type" value="CNAME">`
|
||||||
|
res += `<input name="recordcontent" placeholder="Data">`
|
||||||
|
res += `<input type="submit" name="editrecord" value="Submit">`
|
||||||
|
res += `</form>`
|
||||||
|
res += `</main>`
|
||||||
|
w.Write([]byte(res))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Post(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
_, err := request(
|
||||||
|
r.FormValue("editrecord"),
|
||||||
|
r.FormValue("recordid"),
|
||||||
|
r.FormValue("recordname"),
|
||||||
|
r.FormValue("recordtype"),
|
||||||
|
r.FormValue("recordcontent"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
w.Write([]byte("An error occurred"))
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Add("Location", "/")
|
||||||
|
w.WriteHeader(http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
var BadResponseError = errors.New("Bad response")
|
||||||
|
|
||||||
|
type Record struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
Content string
|
||||||
|
}
|
||||||
|
|
||||||
|
func request(editrecord, recordid, recordname, recordtype, recordcontent string) ([]Record, error) {
|
||||||
|
log.Println("Operation", editrecord, recordid, recordname, recordtype, recordcontent)
|
||||||
|
body := "email=" + username + "&pass=" + password + "&account="
|
||||||
|
body += "&menu=edit_zone&hosted_dns_editzone=1&hosted_dns_zoneid=" + zoneid
|
||||||
|
if len(editrecord) > 0 {
|
||||||
|
if editrecord == "Delete" {
|
||||||
|
body += "&hosted_dns_delconfirm=DELETE&hosted_dns_delrecord=1"
|
||||||
|
} else {
|
||||||
|
body += "&hosted_dns_editrecord=" + editrecord
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(recordid) > 0 {
|
||||||
|
body += "&hosted_dns_recordid=" + recordid
|
||||||
|
}
|
||||||
|
if len(recordname) > 0 {
|
||||||
|
body += "&Name=" + recordname
|
||||||
|
}
|
||||||
|
if len(recordtype) > 0 {
|
||||||
|
body += "&Type=" + recordtype
|
||||||
|
}
|
||||||
|
body += "&TTL=300"
|
||||||
|
if len(recordcontent) > 0 {
|
||||||
|
body += "&Content=" + recordcontent
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := strings.NewReader(body)
|
||||||
|
resp, err := http.Post("https://dns.he.net", "application/x-www-form-urlencoded", buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, BadResponseError
|
||||||
|
}
|
||||||
|
return parseRequest(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRequest(resp *http.Response) ([]Record, error) {
|
||||||
|
d := html.NewTokenizer(resp.Body)
|
||||||
|
records := make([]Record, 0)
|
||||||
|
working := Record{}
|
||||||
|
tdCount := 0
|
||||||
|
|
||||||
|
var err error
|
||||||
|
for err == nil {
|
||||||
|
tok := d.Next()
|
||||||
|
switch tok {
|
||||||
|
case html.ErrorToken:
|
||||||
|
err = d.Err()
|
||||||
|
case html.TextToken:
|
||||||
|
text := string(d.Text())
|
||||||
|
switch tdCount {
|
||||||
|
case 2:
|
||||||
|
working.Name = text
|
||||||
|
case 3:
|
||||||
|
working.Type = text
|
||||||
|
case 6:
|
||||||
|
working.Content = text
|
||||||
|
}
|
||||||
|
case html.StartTagToken:
|
||||||
|
tagName, _ := d.TagName()
|
||||||
|
tagAttr := make(map[string]string)
|
||||||
|
var k, v []byte
|
||||||
|
more := true
|
||||||
|
for more {
|
||||||
|
k, v, more = d.TagAttr()
|
||||||
|
tagAttr[string(k)] = string(v)
|
||||||
|
}
|
||||||
|
if string(tagName) == "tr" {
|
||||||
|
if tagAttr["class"] == "dns_tr" || tagAttr["class"] == "dns_tr_dynamic" {
|
||||||
|
tdCount = 0
|
||||||
|
working = Record{}
|
||||||
|
}
|
||||||
|
if _, ok := tagAttr["id"]; ok {
|
||||||
|
working.ID = tagAttr["id"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case html.EndTagToken:
|
||||||
|
tagName, _ := d.TagName()
|
||||||
|
if string(tagName) == "tr" {
|
||||||
|
if len(working.ID) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
records = append(records, working)
|
||||||
|
} else if string(tagName) == "td" {
|
||||||
|
tdCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return records, err
|
||||||
|
}
|
Loading…
Reference in New Issue