fix: restore tree dropped by 6d224861; land stem95su gdrive-sync (10m) [ci skip]
6d224861 came from a --no-checkout worktree whose empty index made the
commit drop every file except two. This restores 05b50d2b's full tree and
correctly adds stacks/stem95su/gdrive-sync.tf + the service-catalog stem95su
entry. Forward-only (parent=6d224861, no force-push); [ci skip] since the
live infra was never applied from the broken commit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6d224861c4
commit
fd0f4a0365
1166 changed files with 358546 additions and 0 deletions
231
cli/main.go
Normal file
231
cli/main.go
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
useCaseFlagName = "use-case"
|
||||
repoRootFlagName = "repo-root"
|
||||
printResultOnlyFlagName = "result-only"
|
||||
dynamicDnsDomainDefault = "viktorbarzin.ddns.net"
|
||||
publicDomainDefault = "viktorbarzin.me"
|
||||
)
|
||||
|
||||
var (
|
||||
validUseCases = []string{vpnUseCaseFlagName, setupOpenWRTDNSFlagName, addEmailAliasUseCase}
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
if err != nil {
|
||||
glog.Errorf("run failed: %s", err.Error())
|
||||
os.Exit(255)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
useCase := flag.String(useCaseFlagName, "", fmt.Sprintf("Use case to run. Available use cases are: %+v", validUseCases))
|
||||
printResultOnly := flag.Bool(printResultOnlyFlagName, false, "Whether or not to print only the result (allocated ip) or print full command logging")
|
||||
// repoRootParam := flag.String(repoRootFlagName, "", fmt.Sprintf("Path to the root of the infra repository."))
|
||||
|
||||
// VPN flags
|
||||
vpnClientName := flag.String(vpnClientNameFlagName, "", fmt.Sprintf("Friendly VPN user name."))
|
||||
vpnClientPubKey := flag.String(vpnClientPubKeyFlagName, "", fmt.Sprintf("VPN client public key."))
|
||||
|
||||
// OpenWRT DNS flags
|
||||
openWRTNewDNS := flag.String(setupOpenWRTNewDNSFlagName, "", fmt.Sprintf("New DNS server to set."))
|
||||
|
||||
// add email alias flags
|
||||
emailToForwardTo := flag.String(emailAliasFlagName, "", "Email which is used to forward emails to.")
|
||||
fromDomain := flag.String(fromEmailDomainFlagName, "@viktorbarzin.me", "Domain name which will receive emails. Example @viktorbarzin.me")
|
||||
|
||||
// settings for updating the main domain using the dyndns domain
|
||||
dynDnsDomain := flag.String(dynDnsDomainFlagName, dynamicDnsDomainDefault, "Dynamic DNS domain to check against - used to update the main domain")
|
||||
publicDomain := flag.String(publicDomainFlagName, publicDomainDefault, "Public domain to update")
|
||||
|
||||
// Flag definitions above!
|
||||
flag.Parse()
|
||||
|
||||
if !*printResultOnly {
|
||||
flag.Set("logtostderr", "true")
|
||||
flag.Set("stderrthreshold", "WARNING")
|
||||
flag.Set("v", "2")
|
||||
}
|
||||
|
||||
// if *repoRootParam == "" {
|
||||
// return fmt.Errorf("'-%s' flag must not be empty", repoRootFlagName)
|
||||
// }
|
||||
if *useCase == "" {
|
||||
return fmt.Errorf("'-%s' flag must not be empty", useCaseFlagName)
|
||||
}
|
||||
// repoRoot, err := filepath.Abs(*repoRootParam)
|
||||
// if err != nil {
|
||||
// return errors.Wrapf(err, "failed to create absolute path from %s", repoRoot)
|
||||
// }
|
||||
|
||||
glog.Infof("Use case is: %s", *useCase)
|
||||
// glog.Infof("Repo root is: %s", repoRoot)
|
||||
var err error
|
||||
|
||||
switch *useCase {
|
||||
case vpnUseCaseFlagName:
|
||||
gitFs, err := NewGitFS(repository)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to initialize git fs")
|
||||
}
|
||||
worktree, err := gitFs.repo.Worktree()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get worktree")
|
||||
}
|
||||
|
||||
// get last used ip and increment
|
||||
ip, err := getAndUpdateIP(gitFs, vpnLastIPConfFileRelative)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get valid last ip from file %s", vpnLastIPConfFileRelative)
|
||||
}
|
||||
// insert new vpn client config
|
||||
err = addVPNClient(gitFs, *vpnClientName, *vpnClientPubKey, vpnClientsConfFileRelative, ip)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to add vpn client")
|
||||
}
|
||||
// commit changes
|
||||
if _, err = worktree.Commit("Added new VPN client config", &git.CommitOptions{All: true, Author: &object.Signature{Name: "Webhook Handler Bot"}}); err != nil {
|
||||
return errors.Wrapf(err, "failed to commit")
|
||||
}
|
||||
if *printResultOnly {
|
||||
println(ip)
|
||||
}
|
||||
if err = gitFs.Push(); err != nil {
|
||||
return errors.Wrapf(err, "failed to push changes")
|
||||
}
|
||||
case setupOpenWRTDNSFlagName:
|
||||
if *openWRTNewDNS == "" {
|
||||
return fmt.Errorf("New DNS cannot be empty")
|
||||
}
|
||||
if sshKeyPath == "" {
|
||||
return fmt.Errorf("Env variable %s must be set to the location of the private key to use", sshKeyPath)
|
||||
}
|
||||
key, err := ioutil.ReadFile(sshKeyPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to read private key")
|
||||
}
|
||||
output, err := SetOpenWRTDNS(key, *openWRTNewDNS)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, fmt.Sprintf("cmd output: %s", output))
|
||||
}
|
||||
if *printResultOnly {
|
||||
println(fmt.Sprintf("Successfully set DNS server to '%s'", *openWRTNewDNS))
|
||||
}
|
||||
case addEmailAliasUseCase:
|
||||
if *emailToForwardTo == "" {
|
||||
return fmt.Errorf("%s must not be empty when using %s use case", emailAliasFlagName, addEmailAliasUseCase)
|
||||
}
|
||||
glog.Infof("Trying to add %s email alias", *emailToForwardTo)
|
||||
gitFs, err := NewGitFS(repository)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to initialize git fs")
|
||||
}
|
||||
worktree, err := gitFs.repo.Worktree()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get worktree")
|
||||
}
|
||||
emailAlias, err := addEmailAlias(gitFs, *emailToForwardTo, *fromDomain)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to add email alias")
|
||||
}
|
||||
glog.Infof("generated %s email alias", emailAlias)
|
||||
// commit changes
|
||||
if _, err = worktree.Commit("Added new email alias", &git.CommitOptions{All: true, Author: &object.Signature{Name: "Webhook Handler Bot"}}); err != nil {
|
||||
return errors.Wrapf(err, "failed to commit")
|
||||
}
|
||||
if *printResultOnly {
|
||||
fmt.Printf("Successfully created '%s' -> '%s' forwarding", emailAlias, *emailToForwardTo)
|
||||
// println(ip)
|
||||
}
|
||||
if err = gitFs.Push(); err != nil {
|
||||
return errors.Wrapf(err, "failed to push changes")
|
||||
}
|
||||
glog.Infof("successfully added %s -> %s email aliasing", emailAlias, *emailToForwardTo)
|
||||
case updatePublicIPUseCaseFlagName:
|
||||
// Resolve the dynamic dns record
|
||||
publicDNSIps, err := net.LookupIP(*publicDomain)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to resolve IP addresses")
|
||||
}
|
||||
if len(publicDNSIps) < 1 {
|
||||
return fmt.Errorf("no ips found for %s", *dynDnsDomain)
|
||||
}
|
||||
var publicDNSIp net.IP = nil
|
||||
for _, ip := range publicDNSIps {
|
||||
if ip.To4() != nil {
|
||||
publicDNSIp = ip
|
||||
}
|
||||
}
|
||||
if publicDNSIp == nil {
|
||||
return errors.Wrapf(err, "failed to resolve IPv4 address for dyndns")
|
||||
}
|
||||
|
||||
// Resolve the dynamic dns record
|
||||
dynamicDNSIps, err := net.LookupIP(*dynDnsDomain)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to resolve IP addresses")
|
||||
}
|
||||
if len(dynamicDNSIps) < 1 {
|
||||
return fmt.Errorf("no ips found for %s", *dynDnsDomain)
|
||||
}
|
||||
var dynamicDNSIp net.IP
|
||||
for _, ip := range dynamicDNSIps {
|
||||
if ip.To4() != nil {
|
||||
dynamicDNSIp = ip
|
||||
}
|
||||
}
|
||||
|
||||
if publicDNSIp.Equal(dynamicDNSIp) {
|
||||
glog.Infof("IPs of dyndns and current ip match, nothing to do: current=%s, dyndns=%s", publicDNSIp, dynamicDNSIp)
|
||||
return nil
|
||||
}
|
||||
// Send notification as glue records can't be modified programatically for godaddy :/
|
||||
defer notifyForIPChange(publicDNSIp, dynamicDNSIp)
|
||||
// setup git repo
|
||||
// Old, code-as-infra based approach
|
||||
// gitFs, err := NewGitFS(repository)
|
||||
// if err != nil {
|
||||
// return errors.Wrapf(err, "failed to initialize git fs")
|
||||
// }
|
||||
// worktree, err := gitFs.repo.Worktree()
|
||||
// if err != nil {
|
||||
// return errors.Wrapf(err, "failed to get worktree")
|
||||
// }
|
||||
// err = updatePublicIP(gitFs, publicDNSIp, dynamicDNSIp)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("failed to update public ip: %w", err)
|
||||
// }
|
||||
// // // commit changes
|
||||
// if _, err = worktree.Commit("Update public ip and ns records", &git.CommitOptions{All: true, Author: &object.Signature{Name: "Webhook Handler Bot"}}); err != nil {
|
||||
// return errors.Wrapf(err, "failed to commit")
|
||||
// }
|
||||
// if err = gitFs.Push(); err != nil {
|
||||
// return errors.Wrapf(err, "failed to push changes")
|
||||
// }
|
||||
username := os.Getenv("TECHNITIUM_USERNAME")
|
||||
password := os.Getenv("TECHNITIUM_PASSWORD")
|
||||
// dynamicDNSIp = net.ParseIP("6.9.6.9")
|
||||
return UpdatePublicIPViaTechnitiumAPI(dynamicDNSIp, username, password)
|
||||
default:
|
||||
err = errors.New(fmt.Sprintf("unsupported use case: %s", *useCase))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue