-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdyn_sh.functions
319 lines (274 loc) · 8.28 KB
/
dyn_sh.functions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#!/bin/bash
info='
dyn_api is both function that runs curl and the url of the api
http://dyn.com/blog/dynect-api-example-curl-managed-dns-aws-heroku-devops/
DynECT Managed DNS API: Get Started Using CURL, Java or Python'
export dyn_api=https://api.dynect.net
function dyn_api_path () {
local domain id name type fqdn
args2vars "$@" || return 1
[[ -n $domain ]] || return 1
if [[ -z $type ]] ; then
echo $dyn_api/REST/Zone/$domain
return
fi
[[ -n $name ]] || return 2
if [[ x$name == x@ ]] ; then
fqdn=$domain
fi
if [[ $name =~ ${domain}$ ]] ; then
fqdn=$name
else
fqdn=${name}.$domain
fi
if [[ -n $id ]] ; then
echo $dyn_api/REST/${type}Record/${domain}/${fqdn}/${id}
else
echo $dyn_api/REST/${type}Record/${domain}/${fqdn}
fi
}
function dyn_cfg () {
[[ -z ${dyn_customer:0:3} ]] && read -p 'Customer: ' dyn_customer
[[ -z ${dyn_user:0:3} ]] && read -p 'User: ' dyn_user
[[ -z ${dyn_pwd:0:3} ]] && { read -s -p 'Password: ' dyn_pwd ; read_nl ; }
}
function dyn_token_get () {
if [[ -n $dyn_token ]] && (( $(date +%s) - ${dyn_token_ts:-0} < 300 )) ; then
local info="Nothing to do"
return 0
else
dyn token kill
fi
local data=$( jq -n '{
"customer_name": "'$dyn_customer'",
"user_name": "'${dyn_user}'",
"password": "'${dyn_pwd}'"
}')
res=$(curl -Ss -H content-type:application/json --data "$data" -X POST $dyn_api/REST/Session)
# res=$(w3m -header content-type:application/json -post <(echo "$data") -dump_source $dyn_api/REST/Session)
#res=$(http POST $dyn_api/REST/Session content-type:application/json user_name=$dyn_user customer_name=$dyn_customer password=$dyn_pwd )
if dyn_token=$( echo $res | jq -e -r .data.token ) ; then
export dyn_token dyn_token_ts=$(date +%s)
echo new token $(api_history) | info_green | 1>&2
return 0
else
return 1
fi
# function returns error if jq fails
}
function dyn_token_kill () {
# destroy token
[[ -n $dyn_token ]] || return
local res
curl -Ss -H content-type:application/json -H Auth-Token:\ $dyn_token -X DELETE $dyn_api/REST/Session >/dev/zero
# Testing X-HTTP-Method-Override:DELETE. Can't get it work
# w3m -header content-type:application/json -header Auth-Token:$dyn_token -header X-HTTP-Method-Override:DELETE -dump_source $dyn_api/REST/Session
unset dyn_token dyn_token_ts
}
function dyn_token_revive () {
[[ -n $dyn_token ]] || return
curl -Ss -H content-type:application/json -H Auth-Token:\ $dyn_token -X PUT $dyn_api/REST/Session |
jq -e -r .status 2>/dev/zero | egrep -q success
}
function dyn_api () {
local exit_code api_args src msgs
dyn token get
api_args="$*"
api_history=$(api_history)
res_info="src: $api_history \n args: $api_args"
# curl -S -s stops printing errors. The order matters
res=$( curl -s -S -m 33 -H content-type:application/json -H Auth-Token:\ $dyn_token "$@" 2>&1)
res_code=$?
if [[ x$res_code != x0 ]] ; then
(( res_code = res_code + 10 ))
echo -e " res_code: $res_code \n $res_info \n curl_error: $res" | error_red
return $res_code
fi
# set +x ; echo
# login: There was a problem with your credentials
if ! echo $res | is_json ; then
res_code=2
echo -e " res_code: $res_code \n $res_info \n info: not json format" | error_red
if echo $res | fgrep -i -q '<html>' ; then
echo $res | lynx -dump --stdin
else
echo $res
fi | error_red
return $res_code
fi
local debug="
$(echo $res | jq .)" # for debugging purposes
# If we got that far, that means that the request has reached API and the token was renewed
dyn_token_ts=$(date +%s)
if echo $res | jq -e -r .status 2>/dev/zero | egrep -q success ; then
res_code=0
return $res_code
else
res_code=1
echo -e " res_code: $res_code \n $res_info" | error_red
echo "$res" | jq . | error_red
return $res_code
fi
}
function dyn_msg () { # to print messages of success for functions like publish or record create
cat /dev/stdin | jq -e '{ function: "'${FUNCNAME[1]}'", msgs: [.msgs[].INFO] }'
}
function dyn_publish () {
local info='
Checking for pending changes
dyn_api $dyn_api/REST/ZoneChanges/$domain | jq'
[[ -n $2 ]] && local domain=$2 || return 3
if [[ $1 == zone ]] ; then
# to publish new zone
dyn_api -X PUT --data '{"publish":true,"zone":"'$domain'"}' $dyn_api/REST/Zone/$domain/
elif [[ $1 == changes ]] ; then
dyn api -X PUT --data '{"publish":true}' $dyn_api/REST/Zone/$domain/
fi && echo $res | dyn_msg 1>&2
}
dyn_domain_ls () {
if [[ -z $1 ]] ; then
dyn_api $dyn_api/REST/Zone/
echo $res | jq -r .data[] | cut -d/ -f4
return
fi
local domain=$1 id name type
dyn_api $dyn_api/REST/AllRecord/$domain/ || return
echo $res |
{ echo -e "Id \t Name \t Type" ;
# echo $res |
jq -r .data[] |
cut -d / --output-delimiter=\ -f 3,5,6 |
while read type name id ; do
type=${type%Record}
[[ $type =~ SOA|NS ]] && continue
[[ $name =~ ^$domain$ ]] && name=@
[[ $name =~ .+$domain$ ]] && name=${name%.$domain}
echo -e "$id \t $name \t $type"
done ; } | tabs2table
}
function dyn_record2table () {
# jq .data.rdata | jq --stream -j 'select((.[1]|type)=="number") | .[0][],"=",.[1],"," '
# jq -j '.data.rdata | (keys[] as $k | $k, "=", .[$k],","),"\n" '
cat /dev/stdin |
jq -c -j ' .data |
.value = (.rdata | .. | strings) |
.rdata = [ (
.rdata | keys[] as $k |
if .[$k]|type=="number"
then
$k + "=" + ( .[$k] | tostring )
else
empty
end
) ] |
if .rdata | length == 0 then .rdata="-" else .rdata=( .rdata | join(",") ) end |
.zone , " " , .record_id , " " , .fqdn , " " , .record_type , " " , (.ttl|tostring) , " " , .rdata , " " , .value ,
"\n" ' | while
read domain id name type ttl rdata value ; do
[[ $name == $domain ]] && name=@ || name=${name%.$domain}
echo -e "$id \t $name \t $type \t $ttl \t $rdata \t $value"
done
}
function dyn_record_ls () {
local domain ids
if [[ -z $2 ]] ; then
cat << EOF 1>&2
Usage: <command> <domain> all
<command> <domain> naked
<command> <domain> <record1 id> <record2 id> ...
EOF
return 1
fi
domain=$1
shift
local domain_ls=$( dyn domain ls $domain |
if [[ $1 == all ]] ; then
egrep '^[0-9]+'
elif [[ $1 == naked ]] ; then
awk '{ if ( $2 == "@" ) print; }'
else
ids=$( echo $* | tr ' ' '|') # --> id1|id2|id3
egrep "^($ids)\s"
fi )
local id name type req_total=$(echo "$domain_ls"| wc -l)
while read id name type ; do
[[ -z $name ]] && continue
[[ $name == @ ]] && name=$domain || name=${name}.$domain
local cache=$dyn_domains_dir/${domain}.$id
export cache
[[ x$dyn_use_cache =~ x[Oo][Nn] ]] && jq -e -r .status $cache 2>/dev/zero | egrep -q success
local exit_code=$?
if [[ x$exit_code == x0 ]] ; then
continue
fi
(
local dyn_token dyn_token_ts ;
dyn_api https://api.dynect.net/REST/${type}Record/${domain}/${name}/${id} &&
echo $res > $cache
dyn token kill
)&
# w3m can do POST and GET requests with no curl overload
# ( local dyn_token dyn_token_ts ; dyn token get ; res=$(w3m -header content-type:application/json -header Auth-Token:$dyn_token -dump_source https://api.dynect.net/REST/${type}Record/${domain}/${name}/${id}) && echo $res > $cache ; dyn token kill )&
((count++))
if (( count % 50 == 0 || count == req_total )) ; then
wait
fi
done < <(echo "$domain_ls") | cat # cat is to hide background tasks
#echo "$domain_ls"
{
echo -e "Id \t Name \t Type \t TTL \t Rdata \t Target/Value" ;
local ids=$(echo "$domain_ls" | egrep -o '^[0-9]+') ;
for id in $ids ; do
cache=$dyn_domains_dir/${domain}.$id
cat $cache
#jq -e . $cache || return
done | dyn_record2table ;
# TODO: jq '.data |. + .rdata | del(.rdata)'
} | tabs2table
}
function dyn_ls () {
local dyn_token dyn_token_ts
if [[ -n $2 ]] ; then
dyn_record_ls $@
elif [[ $1 == cache ]] ; then
fgrep -l '"rdata"' /dev/shm/oskars/dyn/domains/* | sort
else
dyn_domain_ls $@
fi
dyn token kill
}
function dyn_debug () {
[[ x$dyn_debug == xdebug ]] && echo $* 1>&2
}
function dyn_tmpfile () {
echo $dyn_work_dir/${FUNCNAME[1]}.$BASHPID
}
function dyn () {
[[ -z $dyn_pid ]] && export dyn_pid=$BASHPID
# export dyn_debug=off
# export dyn_use_cache=on
dyn_work_dir=/dev/shm/$USER/dyn
dyn_domains_dir=$dyn_work_dir/domains
dyn_work_dir=$dyn_work_dir/run
export dyn_domains_dir dyn_work_dir
mkdir -p $dyn_work_dir $dyn_domains_dir
dyn_cfg
local action=$1
shift
case x$action in
xdomain|xrecord|xcache|xtoken)
action=${action}_$1
shift
dyn_$action "$@"
# dyn ll cache -> dyn_ll_cache
# dyn domain rm 12345 -> dyn_domain_rm 12345
;;
x)
;;
*)
dyn_$action "$@"
# dyn ll -> dyn_ll
# dyn ll 12345 -> dyn_ll 12345
;;
esac
} # end function dyn