mirror of
https://github.com/urbit/shrub.git
synced 2024-12-15 04:22:48 +03:00
complete unified interface, actions & imgs left
This commit is contained in:
parent
23b190e9de
commit
6e904f5b6f
@ -13,31 +13,22 @@
|
||||
|
||||
!:
|
||||
|%
|
||||
++ droplet
|
||||
$: id=@ud name=@t memory=@ud vcpus=@ud disk=@ud locked=?
|
||||
created=@t status=@t backup-ids=(list ,@t) snapshot-ids=(list ,@ud)
|
||||
features=(list ,@t) region=regi image=img
|
||||
size=syze size-slug=@t networks=ntwrks kernel=kern
|
||||
next-backup-window=json
|
||||
++ instance
|
||||
$: plat=?(%do %gce) name=@t id=@t status=@t created=@da snapshot=name=@t ::disk=@u region=@t
|
||||
ip=(list ,@if)
|
||||
==
|
||||
++ regi ,[name=@t slug=@t sizes=(list ,@t)]
|
||||
++ kern ,[id=@ud name=@t version=@t]
|
||||
++ img
|
||||
$: id=@ud name=@t distribution=@t slug=(unit ,@t) public=? regions=(list ,@t)
|
||||
created-at=@t type=@t min-disk-size=@ud
|
||||
==
|
||||
++ ntwrks ,[v4=(list v) v6=(list v)]
|
||||
++ v ,[ip-address=@t netmask=@t gateway=@t type=@t]
|
||||
++ syze
|
||||
$: memory=@ud price-monthly=@t price-hourly=@t disk=@ud vcpus=@ud
|
||||
slug=@t transfer=@t available=? regions=(list ,@t)
|
||||
==
|
||||
++ reqbody
|
||||
++ create-req-do
|
||||
$:
|
||||
name=@t region=@t size=@t image=@ud ssh=(list cord)
|
||||
backups=(unit ,?) ipv6=(unit ,?) private-networking=(unit ,?) user-data=(unit ,@t)
|
||||
name=@t ::region=@t
|
||||
size=@t image=@t ssh=(list cord)
|
||||
backups=(unit ,?) ipv6=(unit ,?)
|
||||
private-networking=(unit ,?) user-data=(unit ,@t)
|
||||
==
|
||||
++ create-req-gce ,[project=@t zone=@t name=@t machine-type=@t]
|
||||
++ axle
|
||||
$: auth=[do=keys gce=keys] toke=[do=tokens gce=tokens]
|
||||
insts=(map ,@t instance)
|
||||
==
|
||||
++ axle ,[auth=[do=keys gcp=keys] toke=tokens drops=(list droplet)]
|
||||
++ keys ,[authc=(unit ,@t) client-secret=(unit ,@t)]
|
||||
++ tokens ,[access=@t refresh=@t]
|
||||
++ move ,[bone card]
|
||||
@ -49,113 +40,111 @@ $% [%diff %json json]
|
||||
==
|
||||
--
|
||||
!:
|
||||
|% :::
|
||||
++ parse-img
|
||||
=> jo
|
||||
%- ot
|
||||
:~ id/ni name/so distribution/so slug/(mu so) public/bo
|
||||
regions/(ar so) 'created_at'^so type/so 'min_disk_size'^ni
|
||||
==
|
||||
++ parse-ntwrks
|
||||
|% :::
|
||||
++ parse-iso8601
|
||||
=< (cook to-time (parsf ;"{parse-day}T{parse-seconds}{parse-zone}"))
|
||||
|%
|
||||
++ to-time
|
||||
|= [[y=@u m=@u d=@u] t=[h=@u m=@u s=@u ms=@u] [syn=? zh=@u zm=@u]]
|
||||
^- @da
|
||||
%- year
|
||||
^- date
|
||||
=: h.t ?:(syn (sub h.t zh) (add h.t zh))
|
||||
m.t ?:(syn (sub m.t zm) (add m.t zm))
|
||||
==
|
||||
[[& y] m d h.t m.t s.t (div (mul ms.t 0x1.0000) 1.000) ~]
|
||||
++ parse-day (parsf ;"{dem}\-{dem}\-{dem}")
|
||||
++ parse-seconds (parsf ;"{dem}:{dem}:{dem}{(optional ;~(pfix dot dem))}")
|
||||
++ optional |*(fel=_rule ;~(pose fel (easy 0)))
|
||||
++ parse-zone
|
||||
;~ pose
|
||||
(cold [& 0 0] (jest 'Z'))
|
||||
(parsf ;"{parse-zone-sign}{dem}:{dem}")
|
||||
==
|
||||
++ parse-zone-sign ;~(plug ;~(pose (cold & lus) (cold | hep)))
|
||||
--
|
||||
++ key-do
|
||||
(mo [%start 'power_on'] [%stop 'shutdown'] [%reboot 'power_cycle'] ~)
|
||||
++ adapter-do
|
||||
|= a=cord
|
||||
(~(got by key-do) a)
|
||||
++ parse-ip-do
|
||||
=> jo
|
||||
%- ot
|
||||
:+ v4/(ar (ot 'ip_address'^so netmask/so gateway/so type/so ~))
|
||||
v6/(ar (ot 'ip_address'^so netmask/so gateway/so type/so ~))
|
||||
~
|
||||
++ parse-size
|
||||
:_ ~ v4/(ar (ot 'ip_address'^(su lip:ag) ~))
|
||||
++ parse-ip-gce
|
||||
=> jo
|
||||
%- ot
|
||||
:~ memory/ni 'price_monthly'^no 'price_hourly'^no disk/ni
|
||||
vcpus/ni slug/so transfer/no available/bo regions/(ar so)
|
||||
==
|
||||
%+ cu |=(a=(list (list ,@if)) `(list ,@if)`(zing a))
|
||||
(ar (ot 'accessConfigs'^(ar (ot 'natIP'^(su lip:ag) ~)) ~))
|
||||
++ tail-url
|
||||
|= a=cord
|
||||
-:(flop q.q:(need (epur a)))
|
||||
++ parse-region
|
||||
=> jo
|
||||
(ot name/so slug/so sizes/(ar so) ~)
|
||||
++ create-body
|
||||
|= $: name=@t region=@t size=@t image=@ud ssh-keys=(list cord)
|
||||
(ot name/so ~)
|
||||
++ parse-id-text
|
||||
|= jon=json
|
||||
?.(?=([?(%n %s) *] jon) ~ (some p.jon))
|
||||
++ create-do-body
|
||||
|= $: name=@t ::region=@t
|
||||
size=@t image=@t ssh-keys=(list cord)
|
||||
backups=(unit ,?) ipv6=(unit ,?) private-networking=(unit ,?) user-data=(unit ,@t)
|
||||
==
|
||||
%- jobe
|
||||
:~ name/s/name region/s/region size/s/size image/(jone image) ::(jone image)
|
||||
:~ name/s/name ::region/s/region
|
||||
size/s/size image/s/image ::(jone image)
|
||||
backups/?~(backups ~ b/u.backups) ipv6/?~(ipv6 ~ b/u.ipv6)
|
||||
'user_data'^?~(user-data ~ s/u.user-data) 'private_networking'^?~(private-networking ~ b/u.private-networking)
|
||||
==
|
||||
++ convert-do
|
||||
|= a=?(%start %stop %reboot)
|
||||
?- a
|
||||
%start
|
||||
'power_on'
|
||||
%stop
|
||||
'shutdown'
|
||||
%reboot
|
||||
'power_cycle'
|
||||
==
|
||||
++ state-to-json
|
||||
|= a=(list droplet)
|
||||
|= a=(list instance)
|
||||
:- %a
|
||||
%+ turn a
|
||||
|= droplet
|
||||
|= instance
|
||||
^- json
|
||||
%- jobe
|
||||
:~ id/`json`(jone id)
|
||||
name/`json`s/name
|
||||
vcpus/`json`(jone vcpus)
|
||||
disk/`json`(jone disk)
|
||||
locked/b/locked
|
||||
created/s/created
|
||||
:~ name/`json`s/name
|
||||
id/s/id
|
||||
status/s/status
|
||||
backup-ids/a/(turn backup-ids |=(el=cord s/el))
|
||||
snapshot-ids/a/(turn snapshot-ids jone)
|
||||
features/a/(turn features |=(el=cord s/el))
|
||||
=+ ^= reg
|
||||
:~ name/s/name.region slug/s/slug.region
|
||||
sizes/a/(turn sizes.region |=(el=cord s/el))
|
||||
==
|
||||
region/(jobe reg)
|
||||
=+ ^= im
|
||||
:~ id/(jone id.image) name/s/name.image distribution/s/distribution.image
|
||||
slug/?~(slug.image ~ s/u.slug.image) public/b/public.image
|
||||
regions/a/(turn regions.image |=(el=cord s/el))
|
||||
created-at/s/created-at.image type/s/type.image
|
||||
min-disk-size/(jone min-disk-size.image)
|
||||
==
|
||||
image/(jobe im)
|
||||
=+ ^= sz
|
||||
:~ memory/(jone memory.size) price-monthly/s/price-monthly.size
|
||||
price-hourly/s/price-hourly.size disk/(jone disk.size) vcpus/(jone vcpus.size)
|
||||
slug/s/slug.size transfer/s/transfer.size available/b/available.size
|
||||
regions/a/(turn regions.size |=(el=cord s/el))
|
||||
==
|
||||
size/(jobe sz)
|
||||
size-slug/s/size-slug
|
||||
=+ ^= nt
|
||||
=+ ^= vobj
|
||||
|= v
|
||||
%- jobe :~
|
||||
ip-address/s/ip-address netmask/s/netmask
|
||||
gateway/s/gateway type/s/type
|
||||
==
|
||||
:~ v4/[%a (turn v4.networks vobj)]
|
||||
v6/[%a (turn v4.networks vobj)]
|
||||
==
|
||||
networks/(jobe nt)
|
||||
kernel/s/'kernel'
|
||||
next-backup-window/s/'valid'
|
||||
created/s/(crip (dust (yore created)))
|
||||
::region/s/region
|
||||
snapshot/s/snapshot
|
||||
:: disk/`json`(jone disk)
|
||||
ip/a/(turn ip |=(a=@if s/(rsh 3 1 (scot %if a))))
|
||||
==
|
||||
--
|
||||
!:
|
||||
|_ [hid=hide vat=axle]
|
||||
::
|
||||
++ prep ,_`.
|
||||
:::
|
||||
::++ prep ,_`.
|
||||
::
|
||||
++ peer
|
||||
|= [[ost=bone you=ship] pax=path]
|
||||
^- [(list move) _+>.$]
|
||||
:_ +>.$
|
||||
=+ lis=(~(tap by insts.vat))
|
||||
[ost %diff %json (state-to-json (turn lis |=(a=[@t instance] +.a)))]~
|
||||
::
|
||||
++ spam
|
||||
|= jon=json
|
||||
%+ turn (~(tap by sup.hid))
|
||||
|= [sub=bone @ pax=path]
|
||||
^- move
|
||||
[sub %diff %json jon]
|
||||
++ auth-queries
|
||||
|= code=cord
|
||||
:~ 'grant_type'^'authorization_code'
|
||||
'code'^code
|
||||
:- 'client_id'
|
||||
'd8f46b95af38c1ab3d78ad34c2157a6959c23eb0eb5d8e393f650f08e6a75c6f'
|
||||
'redirect_uri'^'http://localhost:8443/home/pub/cloud/fab'
|
||||
==
|
||||
++ httpreq
|
||||
|= $: ost=bone pour-path=wire
|
||||
domain=(list cord) end-point=path
|
||||
req-type=$?(%get [%post json]) headers=math
|
||||
req-type=$?(%get %delt [%post json]) headers=math
|
||||
queries=quay
|
||||
==
|
||||
^- move
|
||||
@ -169,206 +158,349 @@ $% [%diff %json json]
|
||||
=+ ^- request=hiss :: cast to hiss
|
||||
:- parsed-url
|
||||
?@ req-type
|
||||
[%get headers ~]
|
||||
[req-type headers ~]
|
||||
[%post headers ~ (tact (pojo +.req-type))]
|
||||
:^ ost %them pour-path
|
||||
`(unit hiss)`[~ request]
|
||||
::
|
||||
++ peer
|
||||
|= [[ost=bone you=ship] pax=path]
|
||||
^- [(list move) _+>.$]
|
||||
:_ +>.$
|
||||
[ost %diff %json (state-to-json drops.vat)]~
|
||||
++ auth-queries
|
||||
|= code=cord
|
||||
:~ 'grant_type'^'authorization_code'
|
||||
'code'^code
|
||||
:- 'client_id'
|
||||
'd8f46b95af38c1ab3d78ad34c2157a6959c23eb0eb5d8e393f650f08e6a75c6f'
|
||||
'redirect_uri'^'http://localhost:8443/home/pub/cloud/fab'
|
||||
==
|
||||
::
|
||||
++ poke-cloud-auth
|
||||
|= [[ost=bone you=ship] [cde=cord typ=cord]]
|
||||
^- [(list move) _+>.$]
|
||||
~& [cde typ]
|
||||
?: =(%do typ)
|
||||
=. authc.do.auth.vat
|
||||
[~ cde]
|
||||
:_ +>.$
|
||||
~
|
||||
=. authc.gcp.auth.vat
|
||||
[~ cde]
|
||||
:_ +>.$ ~
|
||||
=. access.gce.toke.vat
|
||||
cde
|
||||
:_ +>.$
|
||||
:- (list-instances-gce ost)
|
||||
~
|
||||
::
|
||||
++ poke-cloud-secret
|
||||
|= [[ost=bone you=ship] secret=cord typ=cord]
|
||||
^- [(list move) _+>.$]
|
||||
::=+ [newvat code path]=[vat(auth auth.vat) ...]
|
||||
::=. vat newvat
|
||||
?+ typ ~|(missing-platform=typ !!)
|
||||
%do
|
||||
=. client-secret.do.auth.vat
|
||||
[~ secret]
|
||||
:_ +>.$
|
||||
:_ ~
|
||||
%^ httpreq ost /auth
|
||||
%^ httpreq ost /auth-do
|
||||
:^ ~[%digitalocean %cloud] `path`/v1/oauth/token
|
||||
[%post ~]
|
||||
:- ~ `quay`['client_secret'^secret (auth-queries (need authc.do.auth.vat))]
|
||||
%gce
|
||||
=. client-secret.gcp.auth.vat
|
||||
=. client-secret.gce.auth.vat
|
||||
[~ secret]
|
||||
:_ +>.$
|
||||
:_ ~
|
||||
%^ httpreq ost /auth
|
||||
%^ httpreq ost /auth-gce
|
||||
:^ ~[%google %cloud] `path`/v1/oauth/token
|
||||
[%post ~]
|
||||
:- ~ `quay`['client_secret'^secret (auth-queries (need authc.gcp.auth.vat))]
|
||||
:- (mo ['Content-Type' 'application/json' ~] ['Authorization' (cat 3 'Bearer ' access.do.toke.vat) ~] ~)
|
||||
`quay`['client_secret'^secret %'access_token'^(need authc.gce.auth.vat) ~] ::(auth-queries (need authc.gcp.auth.vat))]
|
||||
==
|
||||
::
|
||||
++ receive-auth
|
||||
|= [ost=bone pour-path=path resp=httr]
|
||||
|= [ost=bone pour-path=cord resp=httr]
|
||||
^- [(list move) _+>.$]
|
||||
~| resp
|
||||
=+ body=(rash q:(need r.resp) apex:poja)
|
||||
~| recieve-auth/resp(r body)
|
||||
?+ pour-path !!
|
||||
%auth-do
|
||||
=+ [ac re]=(need ((ot 'access_token'^so 'refresh_token'^so ~):jo body))
|
||||
=: access.toke.vat ac
|
||||
refresh.toke.vat re
|
||||
=: access.do.toke.vat ac
|
||||
refresh.do.toke.vat re
|
||||
==
|
||||
:_ +>.$
|
||||
:~ (list-droplets ost)
|
||||
:~ (list-instances-do ost)
|
||||
(publish ost our.hid [%lin & 'successfully authenticated']~)
|
||||
==
|
||||
%auth-gce
|
||||
:_ +>.$
|
||||
~
|
||||
==
|
||||
::
|
||||
++ poke-json
|
||||
|= [[ost=bone you=ship] act=json]
|
||||
^- [(list move) _+>.$]
|
||||
=+ do=(need ((ot action/so ~):jo act))
|
||||
:_ +>.$
|
||||
:_ ~
|
||||
?+ do !!
|
||||
%list
|
||||
:_ +>.$
|
||||
:- (list-droplets ost)
|
||||
~
|
||||
(list-instances-do ost)
|
||||
::
|
||||
%create
|
||||
:_ +>.$
|
||||
=+ ^- deets=reqbody
|
||||
%- need
|
||||
%. act
|
||||
=> jo
|
||||
%- ot
|
||||
:~ name/so region/so size/so image/(su dem) :: id key:img object
|
||||
ssh/(ar so) backups/(mu bo)
|
||||
'ipv6'^(mu bo) 'priv_networking'^(mu bo) 'user_data'^(mu so)
|
||||
==
|
||||
:- (create-droplet ost deets)
|
||||
~
|
||||
%create-do
|
||||
(create-do ost act)
|
||||
::
|
||||
$? %reboot %'power_cycle' %shutdown %'power_off' %'power_on'
|
||||
%'password_reset' %'enable_ipv6' %'enable_private_networking'
|
||||
%snapshot %upgrade
|
||||
==
|
||||
=+ id=(need ((ot id/no ~):jo act))
|
||||
(droplet-action ost id do)
|
||||
%create-gce-disk
|
||||
(create-gce-disk ost act)
|
||||
::
|
||||
%create-gce
|
||||
(create-gce ost act)
|
||||
::
|
||||
?(%start %stop %reboot %delete)
|
||||
=+ id=(need ((ot id/so ~):jo act))
|
||||
(instance-action ost id do)
|
||||
==
|
||||
::
|
||||
++ droplet-action
|
||||
++ instance-action
|
||||
|= $: os=bone id=@t
|
||||
$= action $?
|
||||
%delete %reboot %'power_cycle' %shutdown %'power_off'
|
||||
%'power_on' %'password_reset' %'enable_ipv6' %'enable_private_networking'
|
||||
%snapshot %upgrade :: add retrieve droplet action
|
||||
%start %stop %reboot %delete
|
||||
== ==
|
||||
:: restore, resize, rebuild, change_kernelm, retrieve droplet action
|
||||
:_ +>.$
|
||||
^- (list move)
|
||||
:_ ~
|
||||
=+ meth=?:(?=(%delete action) %delt [%post (jobe type/s/(convert-do action) ~)])
|
||||
^- move
|
||||
~& 'do i get here?'
|
||||
=+ ^= req
|
||||
%- httpreq :*
|
||||
os /reboot
|
||||
~[%digitalocean %api] /v2/droplets/[id]/actions
|
||||
[%post `json`(jobe type/s/action ~)]
|
||||
(mo ['Content-Type' 'application/json' ~] ['Authorization' (cat 3 'Bearer ' access.toke.vat) ~] ~)
|
||||
os /action-test
|
||||
~[%digitalocean %api]
|
||||
?:(?=(%delt meth) /v2/droplets/[id] /v2/droplets/[id]/actions)
|
||||
meth
|
||||
%^ mo ['Content-Type' 'application/json' ~]
|
||||
['Authorization' (cat 3 'Bearer ' access.do.toke.vat) ~] ~
|
||||
*quay
|
||||
==
|
||||
req
|
||||
|
||||
++ list-droplets
|
||||
|= os=bone
|
||||
=+ ^= lis
|
||||
:~ os /list
|
||||
~[%digitalocean %api] /v2/droplets
|
||||
%get
|
||||
(mo ['Content-Type' 'application/json' ~] ['Authorization' (cat 3 'Bearer ' access.toke.vat) ~] ~)
|
||||
==
|
||||
(httpreq lis)
|
||||
::
|
||||
++ receive-list
|
||||
|= [ost=bone pour-path=path resp=httr]
|
||||
^- [(list move) _+>.$]
|
||||
=+ parsed=(rash q:(need r.resp) apex:poja)
|
||||
~| recieve-list/parsed
|
||||
=+ dar=(need ((ot droplets/(ar some) ~):jo parsed))
|
||||
=+ ^- dropz=(list droplet)
|
||||
~| bad-json/-.dar
|
||||
%+ turn dar
|
||||
|= drp=json
|
||||
++ create-do
|
||||
|= [os=bone act=json]
|
||||
=+ ^- deets=create-req-do
|
||||
%- need
|
||||
%. drp =+ jo
|
||||
%. act
|
||||
=> jo
|
||||
%- ot
|
||||
:~ id/ni name/so
|
||||
memory/ni vcpus/ni disk/ni
|
||||
locked/bo 'created_at'^so status/so
|
||||
'backup_ids'^(ar so) 'snapshot_ids'^(ar ni) features/(ar so)
|
||||
region/parse-region image/parse-img size/parse-size
|
||||
'size_slug'^so networks/parse-ntwrks kernel/(ot id/ni name/so version/so ~)
|
||||
'next_backup_window'^some
|
||||
:~ name/so size/so image/so :: id key:img object region/so
|
||||
ssh/(ar so) backups/(mu bo)
|
||||
'ipv6'^(mu bo) 'priv_networking'^(mu bo) 'user_data'^(mu so)
|
||||
==
|
||||
=. drops.vat
|
||||
dropz
|
||||
=+ buf=`@da`(add ~s10 lat.hid)
|
||||
:_ +>.$
|
||||
:_ (spam (state-to-json drops.vat))
|
||||
[ost %wait /refresh buf]
|
||||
::
|
||||
++ create-droplet
|
||||
|= [os=bone reqbody]
|
||||
=- ~& - -
|
||||
=+ ^- body=json
|
||||
%- create-body :*
|
||||
name region size image ssh backups
|
||||
ipv6 private-networking user-data
|
||||
%- create-do-body :*
|
||||
name.deets size.deets image.deets ssh.deets backups.deets ::region.deets
|
||||
ipv6.deets private-networking.deets user-data.deets
|
||||
==
|
||||
%- httpreq :*
|
||||
os /create
|
||||
os /create-do
|
||||
~[%digitalocean %api] /v2/droplets
|
||||
[%post body]
|
||||
%^ mo ['Content-Type' 'application/json' ~]
|
||||
['Authorization' (cat 3 'Bearer ' access.toke.vat) ~]
|
||||
%^ mo ['Content-Type' 'application/json; charset=utf-8' ~]
|
||||
['Authorization' (cat 3 'Bearer ' access.do.toke.vat) ~]
|
||||
~
|
||||
~
|
||||
==
|
||||
::
|
||||
++ create-gce-disk
|
||||
|= [os=bone act=json] :: num=(unit ,@u)
|
||||
:: =. name ?~(num name ...
|
||||
=+ :- name=(need ((ot name/so ~):jo act))
|
||||
snap=(need ((ot snap/so ~):jo act))
|
||||
=+ ^- body=json
|
||||
(jobe name/s/name %'sourceSnapshot'^s/'compute/v1/projects/urbcloud/global/snapshots/snapshot-1' ~) ::^so/snap ~)
|
||||
%- httpreq
|
||||
:* os /create-gce-disk
|
||||
~['googleapis' 'www'] /compute/v1/projects/urbcloud/zones/us-central1-b/disks
|
||||
[%post body]
|
||||
%^ mo ['Content-Type' 'application/json' ~]
|
||||
['Authorization' (cat 3 'Bearer ' access.gce.toke.vat) ~]
|
||||
~
|
||||
~
|
||||
==
|
||||
++ ask-disk-status
|
||||
|= [os=bone pax=path] ^- move
|
||||
=+ safe=(slav %uv ?~(pax !! -.pax))
|
||||
=+ link=(need (epur ?~(pax !! safe)))
|
||||
=. r.link ['access_token'^access.gce.toke.vat r.link]
|
||||
:^ os %them `wire`/disk-status
|
||||
`(unit hiss)`[~ [link [%get ~ ~]]]
|
||||
::
|
||||
++ disk-status ::receive
|
||||
|= [ost=bone resp=httr]
|
||||
^- [(list move) _+>.$]
|
||||
=+ hcode=p.resp
|
||||
?: =('200' hcode)
|
||||
~| 'did not receive 200' !!
|
||||
=+ :-(parsed=(rash q:(need r.resp) apex:poja) jo)
|
||||
=+ :- status=(need ((ot status/so ~) parsed))
|
||||
lin=(need ((ot 'selfLink'^so ~) parsed))
|
||||
=+ link=(scot %uv lin)
|
||||
?: =('DONE' status)
|
||||
~& resp
|
||||
~& 'boot disk now running, now starting instance'
|
||||
=+ target=(need ((ot 'targetLink'^so ~):jo parsed))
|
||||
=+ nam=-:(flop q.q:(need (epur target)))
|
||||
~& nam
|
||||
::(create-gce-disk ost nam 'tbd')
|
||||
:- ~ +>.$
|
||||
:_ +>.$
|
||||
[ost %wait `path`[%check-status link ~] `@da`(add ~s3 lat.hid)]~ :: refesh every 10 sec
|
||||
::
|
||||
++ create-gce
|
||||
|= [os=bone act=json]
|
||||
=+ ^- deets=create-req-gce
|
||||
%- need
|
||||
%. act
|
||||
=> jo
|
||||
%- ot
|
||||
:~ project/so zone/so name/so %'machine_type'^so
|
||||
==
|
||||
=+ src=(cat 3 'compute/v1/projects/urbcloud/zones/us-central1-b/disks/' name.deets)
|
||||
=+ ^- body=json
|
||||
%- jobe
|
||||
:~ name/s/'name-provided' 'machineType'^s/'zones/us-central1-b/machineTypes/n1-standard-1'
|
||||
:- %disks :- %a :_ ~
|
||||
(jobe boot/b/%.y type/s/'persistent' source/s/src ~)
|
||||
:- 'networkInterfaces' :- %a :_ ~
|
||||
(joba 'network' `json`[%s 'global/networks/default'])
|
||||
==
|
||||
%- httpreq
|
||||
:* `bone`os `path`/create-gce
|
||||
`(list cord)`~['googleapis' 'www'] `path`/compute/v1/projects/urbcloud/zones/us-central1-b/'instances'
|
||||
[%post `json`body]
|
||||
%^ mo ['Content-Type' 'application/json' ~]
|
||||
['Authorization' (cat 3 'Bearer ' access.gce.toke.vat) ~]
|
||||
~
|
||||
`quay`[%key access.gce.toke.vat]~
|
||||
==
|
||||
::
|
||||
++ wake
|
||||
|= [[ost=bone him=ship pour-path=path] ~]
|
||||
?+ -.pour-path !!
|
||||
%refresh
|
||||
%refresh-do
|
||||
:_ +>.$
|
||||
[(list-droplets ost)]~
|
||||
[(list-instances-do ost)]~
|
||||
%refresh-gce
|
||||
:_ +>.$
|
||||
[(list-instances-gce ost)]~
|
||||
%check-status
|
||||
:_ +>.$
|
||||
[(ask-disk-status ost +.pour-path)]~
|
||||
==
|
||||
::
|
||||
++ list-instances-gce
|
||||
|= os=bone
|
||||
=+ ^= lis
|
||||
:* os /list-gce
|
||||
~[%googleapis %www] /compute/v1/projects/urbcloud/zones/['us-central1-a']/'instances'
|
||||
%get ~
|
||||
^- quay
|
||||
[%'access_token' access.gce.toke.vat]~
|
||||
==
|
||||
(httpreq lis)
|
||||
::
|
||||
++ receive-list-gce
|
||||
|= [os=bone resp=httr]
|
||||
^- [(list move) _+>.$]
|
||||
=+ parsed=(rash q:(need r.resp) apex:poja) :: body httr to json
|
||||
=+ items=(need ((ot items/(ar some) ~):jo parsed))
|
||||
=+ ^- ins=(list ,[@t instance])
|
||||
~| 'bad-json'^items
|
||||
%+ turn items
|
||||
|= in=json
|
||||
=- ~! want=*[@t instance] ~! have=- -
|
||||
=< [id .]
|
||||
^- instance
|
||||
:- %gce
|
||||
%- need
|
||||
%. in =+ jo
|
||||
%- ot
|
||||
:~ name/so id/so status/so 'creationTimestamp'^(su parse-iso8601) ::zone/so
|
||||
'machineType'^(cu tail-url so)
|
||||
'networkInterfaces'^parse-ip-gce
|
||||
==
|
||||
=+ ^= new
|
||||
%+ skip ins
|
||||
|=(a=[@t instance] (~(has by insts.vat) id.a))
|
||||
=. insts.vat
|
||||
(~(gas by insts.vat) new)
|
||||
=+ buf=`@da`(add ~s10 lat.hid)
|
||||
:_ +>.$
|
||||
=+ lis=(~(tap by insts.vat))
|
||||
:_ (spam (state-to-json (turn lis |=(a=[@t instance] +.a))))
|
||||
[os %wait /refresh-gce buf]
|
||||
::
|
||||
++ list-instances-do
|
||||
|= os=bone
|
||||
=+ ^= lis
|
||||
:~ os /list-do
|
||||
~[%digitalocean %api] /v2/droplets
|
||||
%get
|
||||
(mo ['Content-Type' 'application/json' ~] ['Authorization' (cat 3 'Bearer ' access.do.toke.vat) ~] ~)
|
||||
==
|
||||
(httpreq lis)
|
||||
::
|
||||
++ receive-list-do
|
||||
|= [ost=bone resp=httr]
|
||||
^- [(list move) _+>.$]
|
||||
=+ parsed=(rash q:(need r.resp) apex:poja) :: parse httr to json
|
||||
~| recieve-list/parsed
|
||||
=+ dar=(need ((ot droplets/(ar some) ~):jo parsed)) :: reparse ar of insts
|
||||
=. insts.vat
|
||||
%- ~(gas by insts.vat)
|
||||
^- dropz=(list ,[@t instance])
|
||||
~| bad-json/-.dar
|
||||
%+ turn dar
|
||||
|= drp=json ^- [@t instance]
|
||||
=- ~! - -
|
||||
=< [id .]
|
||||
^- instance
|
||||
:- %do
|
||||
%- need
|
||||
%. drp
|
||||
=+ jo
|
||||
%- ot
|
||||
:~ name/so id/parse-id-text status/so 'created_at'^(su parse-iso8601) ::region/parse-region
|
||||
image/(ot name/so ~) ::disk/ni
|
||||
networks/parse-ip-do
|
||||
==
|
||||
=+ buf=`@da`(add ~s10 lat.hid)
|
||||
:_ +>.$
|
||||
=+ lis=(~(tap by insts.vat) *(list ,[@t instance]))
|
||||
:_ (spam (state-to-json (turn lis |=(a=[@t instance] +.a))))
|
||||
[ost %wait /refresh-do buf]
|
||||
|
||||
++ thou
|
||||
|= [[ost=bone him=ship pour-path=path] resp=httr]
|
||||
^- [(list move) _+>.$]
|
||||
?+ -.pour-path !!
|
||||
%auth
|
||||
(receive-auth `bone`ost `path`pour-path resp)
|
||||
?+ -.pour-path ~& pour-path !!
|
||||
%auth-do
|
||||
(receive-auth ost -.pour-path resp)
|
||||
::
|
||||
%list
|
||||
(receive-list ost pour-path resp)
|
||||
%auth-gce
|
||||
(receive-auth ost -.pour-path resp)
|
||||
::
|
||||
%list-do
|
||||
(receive-list-do ost resp)
|
||||
%list-gce
|
||||
(receive-list-gce ost resp)
|
||||
:: :_ +>.$
|
||||
:: ~
|
||||
::
|
||||
$?
|
||||
%delete %reboot %'power_cycle' %shutdown %'power_off'
|
||||
%'power_on' %'password_reset' %'enable_ipv6' %'enable_private_networking'
|
||||
%snapshot %upgrade :: add retrieve droplet action
|
||||
%create
|
||||
%create-do %create-gce %action-test
|
||||
==
|
||||
~& resp
|
||||
:_ +>.$ ~
|
||||
::
|
||||
?(%create-gce-disk %disk-status)
|
||||
(disk-status ost resp)
|
||||
::
|
||||
%check-status
|
||||
:_ +>.$ ~[(ask-disk-status ost +.pour-path)]
|
||||
::
|
||||
%pub
|
||||
:_ +>.$ ~
|
||||
|
@ -9,7 +9,6 @@
|
||||
!:
|
||||
^- manx
|
||||
=+ do=(~(get by qix.gas) %'code')
|
||||
=+ g=(~(get by qix.gas) %'access_token')
|
||||
|
||||
;html
|
||||
;head
|
||||
@ -21,10 +20,10 @@
|
||||
;title: DO & GCE Manager
|
||||
==
|
||||
;body
|
||||
;* =+ d=?~(do ~ (trip u.do))
|
||||
=+ g=?~(g ~ (trip u.g))
|
||||
:_ ~
|
||||
;script: authcode='{?~(d g d)}'; console.log(authcode)
|
||||
;script:"""
|
||||
var authcode = \{}
|
||||
authcode.do='{?~(do ~ (trip u.do))}'
|
||||
"""
|
||||
;div#container;
|
||||
;script@"/home/pub/cloud/src/main.js";
|
||||
==
|
||||
|
@ -9,25 +9,130 @@ tr = React.DOM.tr
|
||||
td = React.DOM.td
|
||||
input = React.DOM.input
|
||||
|
||||
function HashToJSON() {
|
||||
var pairs = window.location.hash.slice(1).split('&');
|
||||
var result = {};
|
||||
pairs.forEach(function(pair) {
|
||||
pair = pair.split('=');
|
||||
result[pair[0]] = decodeURIComponent(pair[1] || '');
|
||||
});
|
||||
|
||||
return JSON.parse(JSON.stringify(result));
|
||||
}
|
||||
|
||||
|
||||
DOControls = React.createClass({
|
||||
createDroplet: function(){
|
||||
urb.send({appl: "cloud",
|
||||
data: {
|
||||
action:'create-do',
|
||||
name:$('#name').val(),
|
||||
region:$('#region').val(),
|
||||
size:$('#size').val(),
|
||||
image:$('#image').val(),
|
||||
ssh:[], // $('#ssh').val()]
|
||||
backups:null,//$('#backups').val(),
|
||||
ipv6:null,//$('#ipv6').val(),
|
||||
priv_networking:null,//$('#priv-networking').val(),
|
||||
user_data:null//$('#user-data').val()
|
||||
},
|
||||
mark: "json"})
|
||||
},
|
||||
|
||||
render: function(){
|
||||
href = "https://cloud.digitalocean.com/v1/oauth/authorize?client_id=d8f46b95af38c1ab3d78ad34c2157a6959c23eb0eb5d8e393f650f08e6a75c6f&redirect_uri=http%3A%2F%2Flocalhost%3A8443%2Fhome%2Fpub%2Fcloud%2Ffab&response_type=code&scope=read+write"
|
||||
return (
|
||||
div({}, [
|
||||
div({},
|
||||
a({href:href},"get authcode"),
|
||||
b({onClick:this.props.handleClick('do')}, "Send Authcode")
|
||||
),
|
||||
div({}, [
|
||||
input({id:"appsecret"},
|
||||
b({onClick:this.props.sendSecret('do','#appsecret')}, "Send Secret"))
|
||||
]),
|
||||
|
||||
div({}, [
|
||||
b({onClick:this.createDroplet}, "Create Droplet"),
|
||||
input({id:"name",placeholder:"Name of droplet"}),
|
||||
input({id:"region",placeholder:"Region"}),
|
||||
input({id:"size",placeholder:"Size (str ending in mb"}),
|
||||
input({id:"image",placeholder:"Image"}),
|
||||
input({id:"ssh",placeholder:"ssh keys (optional)"}),
|
||||
input({id:"backups",placeholder:"backups (optional)"}),
|
||||
input({id:"ipv6",placeholder:"ipv6 (boolean, optional)"}),
|
||||
input({id:"user-data",placeholder:" user-data string (optional)"}),
|
||||
input({id:"priv-networking",placeholder:"Private Networking (boolean, optional)"})
|
||||
])
|
||||
])
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
GCEControls = React.createClass({
|
||||
createDroplet: function(){
|
||||
urb.send({
|
||||
appl: 'cloud',
|
||||
data: {action:'create-gce',
|
||||
project:$('#project').val(),
|
||||
zone:$('#zone').val(),
|
||||
name:$('#gname').val(),
|
||||
machine_type:$('#machine_type').val()
|
||||
},
|
||||
mark: 'json'})
|
||||
},
|
||||
|
||||
createDisk: function(){
|
||||
urb.send({
|
||||
appl: 'cloud',
|
||||
data: {action:'create-gce-disk',
|
||||
snap:$('#gsnap').val(),
|
||||
number:$('#number').val(),
|
||||
name:$('#gcpName').val()},
|
||||
mark: 'json'})
|
||||
},
|
||||
|
||||
render: function(){
|
||||
ghref = "https://accounts.google.com/o/oauth2/auth?response_type=token&scope=https://www.googleapis.com/auth/compute&redirect_uri=http://localhost:8443/home/pub/cloud/fab&client_id=719712694742-6htfj2t9s1j2jid92rc4dfq9psrr9qpo.apps.googleusercontent.com"
|
||||
return(
|
||||
div({}, [
|
||||
div({}, [
|
||||
b({onClick:this.createDisk}, 'Create Disk From Image'),
|
||||
input({id:'gcpName',placeholder:'Name for GCE Disk and Instance'}),
|
||||
input({id:'number',placeholder:'Number of instances'}),
|
||||
input({id:'gsnap',placeholder:'Snapshot'})
|
||||
]),
|
||||
div({}, [
|
||||
a({href:ghref},"Get Google Authcode"),
|
||||
b({onClick:this.props.handleClick('gce')}, "Send Google Authcode")
|
||||
]),
|
||||
div({}, [
|
||||
input({id:"gappsecret"},
|
||||
b({onClick:this.props.sendSecret('gce','#gappsecret')}, "Send Google Secret"))
|
||||
]),
|
||||
div({}, [
|
||||
b({onClick:this.createDroplet}, "Create Droplet"),
|
||||
input({id:"project",placeholder:"project"}),
|
||||
input({id:"zone",placeholder:"zone"}),
|
||||
input({id:"gname",placeholder:"Name of droplet"}),
|
||||
input({id:"machine_type",placeholder:"Machine Type"}),
|
||||
//input({id:"image",placeholder:"Image"}),
|
||||
])
|
||||
]))
|
||||
}
|
||||
})
|
||||
|
||||
Droplet = React.createClass({
|
||||
dropletAction:function(id, action){
|
||||
urb.send({
|
||||
appl:"cloud",
|
||||
data: {action: action,
|
||||
id: id}})
|
||||
},
|
||||
|
||||
rebootDroplet: function() {
|
||||
urb.send({
|
||||
appl: "cloud",
|
||||
data: {action: 'reboot',
|
||||
id: this.props.id}})
|
||||
data: {action:action,
|
||||
id:id}})
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var $this = this //local var, else it always points at second
|
||||
var acts = ["reboot","power_cycle","shutdown","power_off","power_on","password_reset",
|
||||
"enable_ipv6","enable_private_networking","snapshot","upgrade"]
|
||||
var acts = ["start","stop","reboot","delete"]
|
||||
var buttons = [];
|
||||
var buttons = acts.map(function(act){
|
||||
console.log($this.props.id)
|
||||
@ -50,10 +155,11 @@ Page = recl({
|
||||
handleClick: function(platform){
|
||||
return function(){
|
||||
console.log(platform);
|
||||
console.log(window.authcode.platform)
|
||||
if(window.authcode.length !== ''){
|
||||
urb.send({
|
||||
appl: "cloud",
|
||||
data: {authcode:window.authcode,
|
||||
data: {authcode:authcode[platform],
|
||||
platform:platform},
|
||||
mark: "cloud-auth"})
|
||||
} else { console.log("nocode") }
|
||||
@ -79,68 +185,18 @@ Page = recl({
|
||||
mark: "json"})
|
||||
},
|
||||
|
||||
createDroplet: function(){
|
||||
urb.send({appl: "cloud",
|
||||
data: {
|
||||
action:'create',
|
||||
name:$('#name').val(),
|
||||
region:$('#region').val(),
|
||||
size:$('#size').val(),
|
||||
image:$('#image').val(),
|
||||
ssh:[], // $('#ssh').val()]
|
||||
backups:null,//$('#backups').val(),
|
||||
ipv6:null,//$('#ipv6').val(),
|
||||
priv_networking:null,//$('#priv-networking').val(),
|
||||
user_data:null//$('#user-data').val()
|
||||
},
|
||||
mark: "json"})
|
||||
},
|
||||
|
||||
render: function(){
|
||||
href = "https://cloud.digitalocean.com/v1/oauth/authorize?client_id=d8f46b95af38c1ab3d78ad34c2157a6959c23eb0eb5d8e393f650f08e6a75c6f&redirect_uri=http%3A%2F%2Flocalhost%3A8443%2Fhome%2Fpub%2Fcloud%2Ffab&response_type=code&scope=read+write"
|
||||
ghref = "https://accounts.google.com/o/oauth2/auth?response_type=token&scope=https://www.googleapis.com/auth/compute&state=someinfo&redirect_uri=http://localhost:8443/home/pub/cloud/fab&client_id=720541965785-jr3c6ijo8abonu9qj77qre1itsdra52r.apps.googleusercontent.com"
|
||||
return (div({}, [
|
||||
div({},
|
||||
a({href:href},[
|
||||
"get authcode"
|
||||
]),
|
||||
b({onClick:this.handleClick('do')}, "Send Authcode")
|
||||
),
|
||||
div({}, [
|
||||
input({id:"appsecret"},
|
||||
b({onClick:this.sendSecret('do','#appsecret')}, "Send Secret"))
|
||||
]),
|
||||
b({onClick:this.getList}, "Get List"),
|
||||
div({},
|
||||
a({href:ghref},[
|
||||
"Get Google Authcode"
|
||||
]),
|
||||
b({onClick:this.handleClick('gce','#gappsecret')}, "Send Google Authcode")
|
||||
),
|
||||
div({}, [
|
||||
input({id:"gappsecret"},
|
||||
b({onClick:this.sendSecret('gce')}, "Send Google Secret"))
|
||||
]),
|
||||
div({}, [
|
||||
b({onClick:this.createDroplet}, "Create Droplet"),
|
||||
input({id:"name",placeholder:"Name of droplet"}),
|
||||
input({id:"region",placeholder:"Region"}),
|
||||
input({id:"size",placeholder:"Size (str ending in mb"}),
|
||||
input({id:"image",placeholder:"Image"}),
|
||||
input({id:"ssh",placeholder:"ssh keys (optional)"}),
|
||||
input({id:"backups",placeholder:"backups (optional)"}),
|
||||
input({id:"ipv6",placeholder:"ipv6 (boolean, optional)"}),
|
||||
input({id:"user-data",placeholder:" user-data string (optional)"}),
|
||||
input({id:"priv-networking",placeholder:"Private Networking (boolean, optional)"})
|
||||
]),
|
||||
div({},
|
||||
this.props.droplets.map(Droplet)
|
||||
)
|
||||
])
|
||||
)
|
||||
return (div({},
|
||||
DOControls({handleClick:this.handleClick,sendSecret:this.sendSecret}),
|
||||
GCEControls({handleClick:this.handleClick,sendSecret:this.sendSecret}),
|
||||
this.props.droplets.map(Droplet)
|
||||
))
|
||||
}
|
||||
})
|
||||
|
||||
var hash = HashToJSON() //pull out hash of query string for gce authcode
|
||||
authcode.gce = hash.access_token
|
||||
|
||||
mounted = React.render(Page({droplets:[]}), $("#container")[0])
|
||||
urb.bind("/", function(err,d) {
|
||||
|
Loading…
Reference in New Issue
Block a user