First version
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Ask Bjørn Hansen 2022-04-03 01:35:23 -07:00
parent 0e680ad189
commit e926800f44
5 changed files with 276 additions and 0 deletions

30
.drone.yml Normal file
View File

@ -0,0 +1,30 @@
kind: pipeline
type: kubernetes
name: default
steps:
- name: test
image: golang:1.18
volumes:
- name: deps
path: /go
commands:
- go test -v
- go build
- name: docker
image: harbor.ntppool.org/ntppool/drone-kaniko:main
pull: always
volumes:
- name: deps
path: /go
settings:
repo: library/locationcode
registry: harbor.ntppool.org
auto_tag: true
tags: SHA7,${DRONE_SOURCE_BRANCH}
cache: true
username:
from_secret: harbor_library_username
password:
from_secret: harbor_library_password

21
Dockerfile Normal file
View File

@ -0,0 +1,21 @@
FROM golang:1.18-alpine3.15 AS build
RUN apk --no-cache add git
WORKDIR /go/src/
ADD . /go/src/
RUN go install -v ./...
FROM alpine:3.15
USER root
RUN apk --no-cache add ca-certificates
RUN addgroup lc && adduser -D -G lc lc
WORKDIR /
COPY --from=build /go/bin/locationcode /bin/
USER lc
RUN mkdir /tmp/data
CMD ["/bin/locationcode", "-data-dir=/tmp/data"]

159
airports.go Normal file
View File

@ -0,0 +1,159 @@
package main
import (
"flag"
"fmt"
"log"
"net/http"
"os"
"path"
"sort"
"strconv"
"strings"
"github.com/golang/geo/s2"
alphafoxtrot "github.com/grumpypixel/go-airport-finder"
"github.com/labstack/echo/v4"
)
type Airport struct {
Name string
Code string
Distance float64
data *alphafoxtrot.Airport
}
func main() {
var dataDir = flag.String("data-dir", "./data", "Data cache directory")
flag.Parse()
validateData(*dataDir)
finder := alphafoxtrot.NewAirportFinder()
// LoadOptions come with preset filepaths
options := alphafoxtrot.PresetLoadOptions(*dataDir)
// filter := alphafoxtrot.AirportTypeLarge | alphafoxtrot.AirportTypeMedium
filter := alphafoxtrot.AirportTypeRunways
// Load the data into memory
if err := finder.Load(options, filter); len(err) > 0 {
log.Println("errors:", err)
}
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "location code service")
})
e.GET("/v1/code", func(c echo.Context) error {
countryISOCode := c.QueryParam("cc")
countryISOCode = strings.ToUpper(countryISOCode)
radiusString := c.QueryParam("radius")
var radiusKM int
if len(radiusString) > 0 {
radiusKM, _ = strconv.Atoi(radiusString)
}
if radiusKM < 10 {
radiusKM = 100
}
latitude, longitude, err := getLatLng(c)
if err != nil {
return c.String(http.StatusBadRequest, fmt.Sprintf("invalid lat or lng: %s", err))
}
ipLocation := s2.LatLngFromDegrees(latitude, longitude)
maxResults := 100
radiusInMeters := float64(radiusKM) * 1000
airportsRaw := finder.FindNearestAirportsByCountry(countryISOCode, latitude, longitude, radiusInMeters, maxResults, filter)
airports := []*alphafoxtrot.Airport{}
for _, ap := range airportsRaw {
if len(ap.IATACode) == 0 {
continue
}
airports = append(airports, ap)
}
llCache := map[int]s2.LatLng{}
for i, ap := range airports {
ll := s2.LatLngFromDegrees(ap.LatitudeDeg, ap.LongitudeDeg)
llCache[i] = ll
}
r := []*Airport{}
for i, airport := range airports {
// fmt.Printf("%d %s: %+v\n", i, airport.Name, airport)
code := strings.ToLower(airport.Country.ISOCode + airport.IATACode)
distance := float64(ipLocation.Distance(llCache[i])) * 6371.01
a := &Airport{
Name: airport.Name,
Code: code,
Distance: distance,
data: airport,
}
r = append(r, a)
}
sort.Slice(r, func(i, j int) bool {
if r[i].data.Type == r[j].data.Type {
return r[i].Distance < r[j].Distance
}
return airports[i].Type < airports[j].Type
})
if len(r) > 10 {
r = r[0:10]
}
fmt.Printf("got %d airports, filtered to %d, returning %d\n", len(airportsRaw), len(airports), len(r))
return c.JSON(http.StatusOK, r)
})
e.Logger.Fatal(e.Start(":8000"))
}
func validateData(dataDir string) {
downloadFiles := false
for _, filename := range alphafoxtrot.OurAirportsFiles {
filepath := path.Join(dataDir, filename)
if _, err := os.Stat(filepath); os.IsNotExist(err) {
downloadFiles = true
break
}
}
if downloadFiles {
fmt.Println("Downloading CSV files from OurAirports.com...")
alphafoxtrot.DownloadDatabase(dataDir)
}
}
func getLatLng(c echo.Context) (float64, float64, error) {
latitudeStr := c.QueryParam("lat") // 37.3793
longitudeStr := c.QueryParam("lng") // -122.12
latitude, err := strconv.ParseFloat(latitudeStr, 64)
if err != nil {
return 0, 0, err
}
longitude, err := strconv.ParseFloat(longitudeStr, 64)
if err != nil {
return 0, 0, err
}
return latitude, longitude, nil
}

22
go.mod Normal file
View File

@ -0,0 +1,22 @@
module go.askask.com/locationcode
go 1.18
require (
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551
github.com/grumpypixel/go-airport-finder v0.0.0-20210902211810-793a4fb1490b
github.com/labstack/echo/v4 v4.7.2
)
require (
github.com/grumpypixel/go-webget v0.0.1 // indirect
github.com/labstack/gommon v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 // indirect
golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 // indirect
golang.org/x/text v0.3.7 // indirect
)

44
go.sum Normal file
View File

@ -0,0 +1,44 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/grumpypixel/go-airport-finder v0.0.0-20210902211810-793a4fb1490b h1:CAT7j8NnDTijm+Mqc49PowzRwffiQwoNTdacBtAaPac=
github.com/grumpypixel/go-airport-finder v0.0.0-20210902211810-793a4fb1490b/go.mod h1:VSzLdQ8TugVDF/ZqngnVa/4budj2JLbC3spdz4eKEd4=
github.com/grumpypixel/go-webget v0.0.0-20210513194017-df576311f21d h1:ZD475Db8FZRfptdzpvWiAQPRkElVrITDmg7yiTN+vk0=
github.com/grumpypixel/go-webget v0.0.0-20210513194017-df576311f21d/go.mod h1:TZ3kzdKP644McT9EqfvX6vRcnoKxAGNJVbUGfDCgbpA=
github.com/grumpypixel/go-webget v0.0.1 h1:JByEaxRKMK3ACvARJCMva1Tb+mKmZPpIDF9gcgf42OU=
github.com/grumpypixel/go-webget v0.0.1/go.mod h1:TZ3kzdKP644McT9EqfvX6vRcnoKxAGNJVbUGfDCgbpA=
github.com/labstack/echo/v4 v4.7.2 h1:Kv2/p8OaQ+M6Ex4eGimg9b9e6icoxA42JSlOR3msKtI=
github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 h1:EN5+DfgmRMvRUrMGERW2gQl3Vc+Z7ZMnI/xdEpPSf0c=
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 h1:QyVthZKMsyaQwBTJE04jdNN0Pp5Fn9Qga0mrgxyERQM=
golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=